diff --git a/lib/useLiveRef.ts b/lib/useLiveRef.ts index 869f439d..fb4bef29 100644 --- a/lib/useLiveRef.ts +++ b/lib/useLiveRef.ts @@ -3,9 +3,6 @@ import {useRef} from 'react'; /** * Creates a mutable reference to a value, useful when you need to * maintain a reference to a value that may change over time without triggering re-renders. - * - * @deprecated This hook breaks the Rules of React, and should not be used. - * The migration effort to remove it safely is not currently planned. */ function useLiveRef(value: T) { const ref = useRef(value); diff --git a/lib/useOnyx.ts b/lib/useOnyx.ts index f2aa7fa4..016eb0f3 100644 --- a/lib/useOnyx.ts +++ b/lib/useOnyx.ts @@ -78,13 +78,11 @@ function useOnyx>( const previousKey = usePrevious(key); const currentDependenciesRef = useLiveRef(dependencies); - const selector = options?.selector; + const currentSelectorRef = useLiveRef(options?.selector); // Create memoized version of selector for performance const memoizedSelector = useMemo(() => { - if (!selector) { - return null; - } + if (!options?.selector) return null; let lastInput: OnyxValue | undefined; let lastOutput: TReturnValue; @@ -93,13 +91,14 @@ function useOnyx>( return (input: OnyxValue | undefined): TReturnValue => { const currentDependencies = currentDependenciesRef.current; + const currentSelector = currentSelectorRef.current; // Recompute if input changed, dependencies changed, or first time const dependenciesChanged = !shallowEqual(lastDependencies, currentDependencies); if (!hasComputed || lastInput !== input || dependenciesChanged) { // Only proceed if we have a valid selector - if (selector) { - const newOutput = selector(input); + if (currentSelector) { + const newOutput = currentSelector(input); // Deep equality mode: only update if output actually changed if (!hasComputed || !deepEqual(lastOutput, newOutput) || dependenciesChanged) { @@ -113,7 +112,7 @@ function useOnyx>( return lastOutput; }; - }, [currentDependenciesRef, selector]); + }, [currentDependenciesRef, currentSelectorRef, options?.selector]); // 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. diff --git a/tests/unit/useOnyxTest.ts b/tests/unit/useOnyxTest.ts index 1438f5b0..afaa6d66 100644 --- a/tests/unit/useOnyxTest.ts +++ b/tests/unit/useOnyxTest.ts @@ -409,6 +409,7 @@ describe('useOnyx', () => { expect(result.current[1].status).toEqual('loaded'); selector = (entry: OnyxEntry<{id: string; name: string}>) => `id - ${entry?.id}, name - ${entry?.name} - selector changed`; + // In a react app we expect the selector ref to change during a rerender (see selectorRef/useLiveRef) rerender(undefined); expect(result.current[0]).toEqual('id - test_id, name - test_name - selector changed');