Skip to content

Commit 0e1a5d7

Browse files
committed
apply additional improvements, add more tests
1 parent ec0ba98 commit 0e1a5d7

2 files changed

Lines changed: 65 additions & 5 deletions

File tree

lib/useOnyx.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import connectionManager from './OnyxConnectionManager';
77
import OnyxUtils from './OnyxUtils';
88
import * as GlobalSettings from './GlobalSettings';
99
import type {CollectionKeyBase, OnyxKey, OnyxValue} from './types';
10-
import usePrevious from './usePrevious';
1110
import decorateWithMetrics from './metrics';
1211
import onyxSnapshotCache from './OnyxSnapshotCache';
1312
import useLiveRef from './useLiveRef';
@@ -57,8 +56,6 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
5756
dependencies: DependencyList = [],
5857
): UseOnyxResult<TReturnValue> {
5958
const connectionRef = useRef<Connection | null>(null);
60-
const previousKey = usePrevious(key);
61-
6259
const currentDependenciesRef = useLiveRef(dependencies);
6360
const selector = options?.selector;
6461

@@ -219,7 +216,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
219216
// so we can return any cached value right away. For the case where the key has changed, If we don't return the cached value right away, then the UI will show the incorrect (previous) value for a brief period which looks like a UI glitch to the user. After the connection is made, we only
220217
// update `newValueRef` when `Onyx.connect()` callback is fired.
221218
const hasSelectorChanged = lastComputedSelectorRef.current !== memoizedSelector;
222-
if (isFirstConnection || shouldGetCachedValueRef.current || key !== previousKey || hasSelectorChanged) {
219+
if (isFirstConnection || shouldGetCachedValueRef.current || hasSelectorChanged) {
223220
// Gets the value from cache and maps it with selector. It changes `null` to `undefined` for `useOnyx` compatibility.
224221
const value = OnyxUtils.tryGetCachedValue(key) as OnyxValue<TKey>;
225222
const selectedValue = memoizedSelector ? memoizedSelector(value) : value;
@@ -283,7 +280,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
283280
}
284281

285282
return resultRef.current;
286-
}, [options?.initWithStoredValues, key, memoizedSelector, cacheKey, previousKey]);
283+
}, [options?.initWithStoredValues, key, memoizedSelector, cacheKey]);
287284

288285
const subscribe = useCallback(
289286
(onStoreChange: () => void) => {

tests/unit/useOnyxTest.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,69 @@ describe('useOnyx', () => {
117117
expect(result.current[0]).toBeUndefined();
118118
expect(result.current[1].status).toEqual('loaded');
119119
});
120+
121+
it('should return the new value when switching from a key with data to another key with different data', async () => {
122+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}1`, 'value_one');
123+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}2`, 'value_two');
124+
125+
const {result, rerender} = renderHook((key: string) => useOnyx(key), {initialProps: `${ONYXKEYS.COLLECTION.TEST_KEY}1` as string});
126+
127+
await act(async () => waitForPromisesToResolve());
128+
129+
expect(result.current[0]).toEqual('value_one');
130+
expect(result.current[1].status).toEqual('loaded');
131+
132+
// Switch to another key that also has data
133+
rerender(`${ONYXKEYS.COLLECTION.TEST_KEY}2`);
134+
135+
await act(async () => waitForPromisesToResolve());
136+
137+
expect(result.current[0]).toEqual('value_two');
138+
expect(result.current[1].status).toEqual('loaded');
139+
});
140+
141+
it('should apply the selector against the new key data when switching keys', async () => {
142+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}1`, {id: 'entry1_id', name: 'entry1_name'});
143+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}2`, {id: 'entry2_id', name: 'entry2_name'});
144+
145+
const selector = ((entry: OnyxEntry<{id: string; name: string}>) => entry?.name) as UseOnyxSelector<OnyxKey, string | undefined>;
146+
147+
const {result, rerender} = renderHook((key: string) => useOnyx(key, {selector}), {initialProps: `${ONYXKEYS.COLLECTION.TEST_KEY}1` as string});
148+
149+
await act(async () => waitForPromisesToResolve());
150+
151+
expect(result.current[0]).toEqual('entry1_name');
152+
expect(result.current[1].status).toEqual('loaded');
153+
154+
// Switch key — selector should run against the new key's data
155+
rerender(`${ONYXKEYS.COLLECTION.TEST_KEY}2`);
156+
157+
await act(async () => waitForPromisesToResolve());
158+
159+
expect(result.current[0]).toEqual('entry2_name');
160+
expect(result.current[1].status).toEqual('loaded');
161+
});
162+
163+
it('should handle rapid key switching and settle on the final key value', async () => {
164+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}1`, 'value_one');
165+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}2`, 'value_two');
166+
Onyx.set(`${ONYXKEYS.COLLECTION.TEST_KEY}3`, 'value_three');
167+
168+
const {result, rerender} = renderHook((key: string) => useOnyx(key), {initialProps: `${ONYXKEYS.COLLECTION.TEST_KEY}1` as string});
169+
170+
await act(async () => waitForPromisesToResolve());
171+
172+
expect(result.current[0]).toEqual('value_one');
173+
174+
// Rapidly switch keys without waiting for promises between switches
175+
rerender(`${ONYXKEYS.COLLECTION.TEST_KEY}2`);
176+
rerender(`${ONYXKEYS.COLLECTION.TEST_KEY}3`);
177+
178+
await act(async () => waitForPromisesToResolve());
179+
180+
expect(result.current[0]).toEqual('value_three');
181+
expect(result.current[1].status).toEqual('loaded');
182+
});
120183
});
121184

122185
describe('misc', () => {

0 commit comments

Comments
 (0)