Skip to content

Commit

Permalink
fix typings
Browse files Browse the repository at this point in the history
  • Loading branch information
kacper-mikolajczak committed Oct 1, 2024
1 parent 24a9e8b commit a16d45f
Showing 1 changed file with 15 additions and 28 deletions.
43 changes: 15 additions & 28 deletions lib/useOnyx.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import {deepEqual, shallowEqual} from 'fast-equals';
import {useCallback, useEffect, useRef, useSyncExternalStore} from 'react';
import type {IsEqual} from 'type-fest';
import OnyxCache from './OnyxCache';
import type {Connection} from './OnyxConnectionManager';
import connectionManager from './OnyxConnectionManager';
import OnyxUtils from './OnyxUtils';
import type {CollectionKeyBase, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue} from './types';
import type {CollectionKeyBase, OnyxKey, OnyxValue} from './types';
import useLiveRef from './useLiveRef';
import usePrevious from './usePrevious';

Expand Down Expand Up @@ -33,6 +32,8 @@ type UseOnyxInitialValueOption<TInitialValue> = {
initialValue?: TInitialValue;
};

type UseOnyxSelector<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>> = (data: OnyxValue<TKey> | undefined) => TReturnValue;

type UseOnyxSelectorOption<TKey extends OnyxKey, TReturnValue> = {
/**
* This will be used to subscribe to a subset of an Onyx key's data.
Expand All @@ -47,17 +48,11 @@ type UseOnyxOptions<TKey extends OnyxKey, TReturnValue> = BaseUseOnyxOptions & U

type FetchStatus = 'loading' | 'loaded';

type SelectedValue<TKey, TValue> = TKey extends CollectionKeyBase ? OnyxCollection<TValue> : OnyxEntry<TValue>;

type CachedValue<TKey extends OnyxKey, TValue> = IsEqual<TValue, OnyxValue<TKey>> extends true ? TValue : SelectedValue<TKey, TValue>;

type ResultMetadata = {
status: FetchStatus;
};

type UseOnyxResult<TKey extends OnyxKey, TValue> = [CachedValue<TKey, TValue>, ResultMetadata];

type UseOnyxSelector<TKey extends OnyxKey, SelectorValue> = (data?: OnyxValue<TKey>) => SelectorValue;
type UseOnyxResult<TValue> = [TValue, ResultMetadata];

/**
* Gets the cached value from the Onyx cache. If the key is a collection key, it will return all the values in the collection.
Expand Down Expand Up @@ -91,23 +86,15 @@ function getCachedValue<TKey extends OnyxKey>(key: TKey): OnyxValue<TKey> | unde
/**
* Gets the value from cache and maps it with selector.
*/
function getSelectedValue<TKey extends OnyxKey, TValue = OnyxValue<TKey> | undefined>(key: TKey, selector?: UseOnyxSelector<TKey, TValue>) {
function getSelectedValue<TKey extends OnyxKey, TValue>(key: TKey, selector?: UseOnyxSelector<TKey, TValue>) {
const value = getCachedValue(key);

const selectedValue = selector ? selector(value) : value;
const selectedValue = (selector ? selector(value) : value) as TValue;

return selectedValue;
}

function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
key: TKey,
options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<TReturnValue> & Required<UseOnyxSelectorOption<TKey, TReturnValue>>,
): UseOnyxResult<TKey, TReturnValue>;
function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
key: TKey,
options?: BaseUseOnyxOptions & UseOnyxInitialValueOption<NoInfer<TReturnValue>>,
): UseOnyxResult<TKey, TReturnValue>;
function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey, options?: UseOnyxOptions<TKey, TReturnValue>): UseOnyxResult<TKey, TReturnValue> {
function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey, options?: UseOnyxOptions<TKey, TReturnValue>) {
const connectionRef = useRef<Connection | null>(null);
const previousKey = usePrevious(key);

Expand All @@ -116,16 +103,16 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey

// Stores the previous cached value as it's necessary to compare with the new value in `getSnapshot()`.
// We initialize it to `null` to simulate that we don't have any value from cache yet.
const previousValueRef = useRef<CachedValue<TKey, TReturnValue> | undefined | null>(null);
const previousValueRef = useRef<TReturnValue | undefined | null>(null);

// Stores the newest cached value in order to compare with the previous one and optimize `getSnapshot()` execution.
const newValueRef = useRef<CachedValue<TKey, TReturnValue> | undefined | null>(null);
const newValueRef = useRef<TReturnValue | undefined | null>(null);

// Stores the previously result returned by the hook, containing the data from cache and the fetch status.
// We initialize it to `undefined` and `loading` fetch status to simulate the initial result when the hook is loading from the cache.
// However, if `initWithStoredValues` is `false` we set the fetch status to `loaded` since we want to signal that data is ready.
const resultRef = useRef<UseOnyxResult<TKey, TReturnValue>>([
undefined as CachedValue<TKey, TReturnValue>,
const resultRef = useRef<UseOnyxResult<TReturnValue | undefined>>([
undefined,
{
status: options?.initWithStoredValues === false ? 'loaded' : 'loading',
},
Expand Down Expand Up @@ -197,7 +184,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey
// If `newValueRef.current` is `null` or any other value it means that the cache does have a value for that key.
// This difference between `undefined` and other values is crucial and it's used to address the following
// conditions and use cases.
newValueRef.current = getSelectedValue(key, selectorRef.current) as CachedValue<TKey, TReturnValue>;
newValueRef.current = getSelectedValue(key, selectorRef.current);

// We set this flag to `false` again since we don't want to get the newest cached value every time `getSnapshot()` is executed,
// and only when `Onyx.connect()` callback is fired.
Expand All @@ -220,7 +207,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey
// If data is not present in cache and `initialValue` is set during the first connection,
// we set the new value to `initialValue` and fetch status to `loaded` since we already have some data to return to the consumer.
if (isFirstConnectionRef.current && !hasCacheForKey && options?.initialValue !== undefined) {
newValueRef.current = (options?.initialValue ?? undefined) as CachedValue<TKey, TReturnValue>;
newValueRef.current = options?.initialValue ?? undefined;
newFetchStatus = 'loaded';
}

Expand All @@ -242,7 +229,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey
previousValueRef.current = newValueRef.current;

// If the new value is `null` we default it to `undefined` to ensure the consumer gets a consistent result from the hook.
resultRef.current = [previousValueRef.current as CachedValue<TKey, TReturnValue>, {status: newFetchStatus ?? 'loaded'}];
resultRef.current = [previousValueRef.current, {status: newFetchStatus ?? 'loaded'}];

Check failure on line 232 in lib/useOnyx.ts

View workflow job for this annotation

GitHub Actions / lint

Type 'TReturnValue | null | undefined' is not assignable to type 'TReturnValue | undefined'.
}

return resultRef.current;
Expand Down Expand Up @@ -285,7 +272,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(key: TKey
checkEvictableKey();
}, [checkEvictableKey]);

const result = useSyncExternalStore<UseOnyxResult<TKey, TReturnValue>>(subscribe, getSnapshot);
const result = useSyncExternalStore(subscribe, getSnapshot);

return result;
}
Expand Down

0 comments on commit a16d45f

Please sign in to comment.