Skip to content

Commit 293484d

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/reassure-phase-2
2 parents 1889ab4 + 2f04430 commit 293484d

8 files changed

Lines changed: 42 additions & 19 deletions

File tree

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20.18.1
1+
20.19.1

lib/Onyx.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,11 @@ function multiSet(data: OnyxMultiSetInput): Promise<void> {
238238

239239
const updatePromises = keyValuePairsToSet.map(([key, value]) => {
240240
const prevValue = cache.get(key, false);
241+
// When we use multiSet to set a key we want to clear the current delta changes from Onyx.merge that were queued
242+
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
243+
if (OnyxUtils.hasPendingMergeForKey(key)) {
244+
delete OnyxUtils.getMergeQueue()[key];
245+
}
241246

242247
// Update cache and optimistically inform subscribers on the next tick
243248
cache.set(key, value);

lib/OnyxUtils.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import {deepEqual} from 'fast-equals';
33
import lodashClone from 'lodash/clone';
44
import type {ValueOf} from 'type-fest';
5-
import lodashPick from 'lodash/pick';
65
import DevTools from './DevTools';
76
import * as Logger from './Logger';
87
import type Onyx from './Onyx';
@@ -1417,9 +1416,8 @@ function updateSnapshots(data: OnyxUpdate[], mergeFn: typeof Onyx.merge): Array<
14171416
}
14181417

14191418
const oldValue = updatedData[key] || {};
1420-
const newValue = lodashPick(value, Object.keys(snapshotData[key]));
14211419

1422-
updatedData = {...updatedData, [key]: Object.assign(oldValue, newValue)};
1420+
updatedData = {...updatedData, [key]: Object.assign(oldValue, value)};
14231421
});
14241422

14251423
// Skip the update if there's no data to be merged

lib/useOnyx.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ function useOnyx<TKey extends OnyxKey, TReturnValue = OnyxValue<TKey>>(
300300
// we log an alert so it can be acknowledged by the consumer. Additionally, we won't log alerts
301301
// if there's a `Onyx.clear()` task in progress.
302302
if (options?.canBeMissing === false && newStatus === 'loaded' && !isOnyxValueDefined && !OnyxCache.hasPendingTask(TASK.CLEAR)) {
303-
Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false.`, {key, showAlert: true});
303+
Logger.logAlert(`useOnyx returned no data for key with canBeMissing set to false for key ${key}`, {showAlert: true});
304304
}
305305
}
306306

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-onyx",
3-
"version": "2.0.105",
3+
"version": "2.0.109",
44
"author": "Expensify, Inc.",
55
"homepage": "https://expensify.com",
66
"description": "State management for React Native",
@@ -126,7 +126,7 @@
126126
}
127127
},
128128
"engines": {
129-
"node": ">=20.18.1",
129+
"node": ">=20.19.1",
130130
"npm": ">=10.8.2"
131131
},
132132
"sideEffects": false

tests/unit/onyxTest.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1448,7 +1448,7 @@ describe('Onyx', () => {
14481448
const snapshot1 = `${ONYX_KEYS.COLLECTION.SNAPSHOT}1`;
14491449

14501450
const initialValue = {name: 'Fluffy'};
1451-
const finalValue = {name: 'Kitty'};
1451+
const finalValue = {name: 'Kitty', nickName: 'Fitse'};
14521452

14531453
await Onyx.set(cat, initialValue);
14541454
await Onyx.set(snapshot1, {data: {[cat]: initialValue}});
@@ -2029,5 +2029,25 @@ describe('Onyx', () => {
20292029
[`${ONYX_KEYS.COLLECTION.TEST_KEY}entry2`]: {id: 'entry2_id', name: 'entry2_name'},
20302030
});
20312031
});
2032+
it('should clear pending merge for a key during multiSet()', async () => {
2033+
const testKey = `${ONYX_KEYS.COLLECTION.TEST_KEY}entry1`;
2034+
2035+
// Mock the merge queue with the correct type
2036+
const mockMergeQueue: Record<string, unknown[]> = {
2037+
[testKey]: [{some: 'mergeData'}],
2038+
};
2039+
2040+
// Mock the utility functions
2041+
jest.spyOn(OnyxUtils, 'hasPendingMergeForKey').mockImplementation((key) => key === testKey);
2042+
jest.spyOn(OnyxUtils, 'getMergeQueue').mockImplementation(() => mockMergeQueue);
2043+
2044+
await Onyx.multiSet({
2045+
[testKey]: {id: 'entry1_id', name: 'entry1_name'},
2046+
});
2047+
2048+
expect(mockMergeQueue[testKey]).toBeUndefined();
2049+
2050+
jest.restoreAllMocks();
2051+
});
20322052
});
20332053
});

tests/unit/useOnyxTest.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -752,7 +752,7 @@ describe('useOnyx', () => {
752752

753753
describe('canBeMissing', () => {
754754
let logAlertFn = jest.fn();
755-
const alertMessage = 'useOnyx returned no data for key with canBeMissing set to false.';
755+
const alertMessage = 'useOnyx returned no data for key with canBeMissing set to false for key test';
756756

757757
beforeEach(() => {
758758
logAlertFn = jest.fn();
@@ -806,7 +806,7 @@ describe('useOnyx', () => {
806806
expect(result1.current[0]).toBeUndefined();
807807
expect(result1.current[1].status).toEqual('loaded');
808808
expect(logAlertFn).toHaveBeenCalledTimes(1);
809-
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
809+
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true});
810810

811811
await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test'));
812812

@@ -816,7 +816,7 @@ describe('useOnyx', () => {
816816

817817
expect(result1.current[0]).toBeUndefined();
818818
expect(logAlertFn).toHaveBeenCalledTimes(2);
819-
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
819+
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true});
820820
});
821821

822822
it('should log an alert if Onyx doesn\'t return selected data in loaded state and "canBeMissing" property is false', async () => {
@@ -837,7 +837,7 @@ describe('useOnyx', () => {
837837
expect(result1.current[0]).toBeUndefined();
838838
expect(result1.current[1].status).toEqual('loaded');
839839
expect(logAlertFn).toHaveBeenCalledTimes(1);
840-
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
840+
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true});
841841

842842
await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test'));
843843

@@ -847,7 +847,7 @@ describe('useOnyx', () => {
847847

848848
expect(result1.current[0]).toBeUndefined();
849849
expect(logAlertFn).toHaveBeenCalledTimes(2);
850-
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
850+
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true});
851851
});
852852

853853
it('should log an alert if Onyx doesn\'t return data but there is a selector that always return something and "canBeMissing" property is false', async () => {
@@ -865,7 +865,7 @@ describe('useOnyx', () => {
865865
expect(result1.current[0]).toBe('undefined_changed');
866866
expect(result1.current[1].status).toEqual('loaded');
867867
expect(logAlertFn).toHaveBeenCalledTimes(1);
868-
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
868+
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true});
869869

870870
await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test'));
871871

@@ -875,7 +875,7 @@ describe('useOnyx', () => {
875875

876876
expect(result1.current[0]).toBe('undefined_changed');
877877
expect(logAlertFn).toHaveBeenCalledTimes(2);
878-
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
878+
expect(logAlertFn).toHaveBeenNthCalledWith(2, alertMessage, {showAlert: true});
879879
});
880880

881881
it('should not log an alert if "canBeMissing" property is false but there is a Onyx.clear() task in progress', async () => {
@@ -890,7 +890,7 @@ describe('useOnyx', () => {
890890
expect(result1.current[0]).toBeUndefined();
891891
expect(result1.current[1].status).toEqual('loaded');
892892
expect(logAlertFn).toHaveBeenCalledTimes(1);
893-
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {key: ONYXKEYS.TEST_KEY, showAlert: true});
893+
expect(logAlertFn).toHaveBeenNthCalledWith(1, alertMessage, {showAlert: true});
894894

895895
await act(async () => Onyx.set(ONYXKEYS.TEST_KEY, 'test'));
896896

0 commit comments

Comments
 (0)