From a5a47eaa321d86f4b8c527e9c27d858499db2206 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal <58412969+shubham1206agra@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:26:22 +0530 Subject: [PATCH] Revert "Remove useLiveRef" --- lib/useLiveRef.ts | 3 --- lib/useOnyx.ts | 13 ++++++------- tests/unit/useOnyxTest.ts | 1 + 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/useLiveRef.ts b/lib/useLiveRef.ts index 869f439db..fb4bef295 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 f2aa7fa49..016eb0f33 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 1438f5b08..afaa6d66f 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');