From 2c2ab18a0ba56c42dc29ad0dcbb9de6348049351 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Mon, 5 Jan 2026 23:01:55 +0100 Subject: [PATCH 1/9] use live onyx data in search if possible --- src/hooks/useOnyx.ts | 64 +++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index db42d64b636d..7889409f8049 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -1,3 +1,5 @@ +import isEmpty from 'lodash/isEmpty'; +import isPlainObject from 'lodash/isPlainObject'; import {use, useMemo} from 'react'; import type {DependencyList} from 'react'; // eslint-disable-next-line no-restricted-imports @@ -58,35 +60,55 @@ const useOnyx: OriginalUseOnyx = > | undefined; - const {selector: selectorProp, ...optionsWithoutSelector} = useOnyxOptions ?? {}; - - // Determine if we should use snapshot data based on search state and key + const {selector, ...optionsWithoutSelector} = useOnyxOptions ?? {}; + + // Original Onyx + const originalOnyxOptions: UseOnyxOptions> = {...optionsWithoutSelector, selector, allowDynamicKey: true}; + const originalResult = originalUseOnyx(key, originalOnyxOptions, dependencies); + + // Snapshot Onyx + /** + * React hooks cannot be called conditionally. Thus we always subscribe to the snapshot data + * and if shouldUseSnapshot is false then the selector always returns false as the data so we don't cause unnecessary renders + * similarly canBeMissing is set to true to avoid falsy warnings. + */ const shouldUseSnapshot = isOnSearch && !!currentSearchHash && isSnapshotCompatibleKey; - - // Create selector function that handles both regular and snapshot data - const selector = useMemo(() => { - if (!selectorProp || !shouldUseSnapshot) { - return selectorProp; + const snapshotSelector = useMemo(() => { + if (!shouldUseSnapshot) { + return () => false; } - return (data: OnyxValue | undefined) => selectorProp(getKeyData(data as SearchResults, key)); - }, [selectorProp, shouldUseSnapshot, key]); + if (!selector) { + return (data: OnyxValue | undefined) => getKeyData(data as SearchResults, key) as OnyxValue; + } - const onyxOptions: UseOnyxOptions> = {...optionsWithoutSelector, selector, allowDynamicKey: true}; - const snapshotKey = shouldUseSnapshot ? (`${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}` as OnyxKey) : key; + return (data: OnyxValue | undefined) => selector(getKeyData(data as SearchResults, key)); + }, [shouldUseSnapshot, selector, key]); + const snapshotOnyxOptions: UseOnyxOptions> = { + ...optionsWithoutSelector, + selector: snapshotSelector, + allowDynamicKey: true, + canBeMissing: shouldUseSnapshot ? optionsWithoutSelector.canBeMissing : true, + }; + const snapshotKey = `${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}` as OnyxKey; + const snapshotResult = originalUseOnyx(snapshotKey, snapshotOnyxOptions, dependencies); + + // Merge original and snapshot onyx results + const result = useMemo((): UseOnyxResult => { + if (shouldUseSnapshot) { + if (isPlainObject(originalResult[0]) && isPlainObject(snapshotResult[0])) { + return [{...(snapshotResult[0] as Object), ...(originalResult[0] as Object)}, originalResult[1]] as UseOnyxResult; + } - const originalResult = originalUseOnyx(snapshotKey, onyxOptions, dependencies); + if (isEmpty(snapshotResult[0])) { + return originalResult as UseOnyxResult; + } - // Extract and memoize the specific key data from snapshot if in search mode - const result = useMemo((): UseOnyxResult => { - // if it has selector, we don't need to use snapshot here - if (!shouldUseSnapshot || selector) { - return originalResult as UseOnyxResult; + return snapshotResult as UseOnyxResult; } - const keyData = getKeyData(originalResult[0] as SearchResults, key); - return [keyData, originalResult[1]] as UseOnyxResult; - }, [shouldUseSnapshot, originalResult, key, selector]); + return originalResult as UseOnyxResult; + }, [shouldUseSnapshot, originalResult, snapshotResult]); return result; }; From 64b3bde45180b4d9e9f33e18246ed68f00721cf9 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Mon, 5 Jan 2026 23:06:20 +0100 Subject: [PATCH 2/9] update comment --- src/hooks/useOnyx.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index 7889409f8049..bcd8b14285ec 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -93,8 +93,8 @@ const useOnyx: OriginalUseOnyx = => { + // Merge snapshot data with live data if possible if (shouldUseSnapshot) { if (isPlainObject(originalResult[0]) && isPlainObject(snapshotResult[0])) { return [{...(snapshotResult[0] as Object), ...(originalResult[0] as Object)}, originalResult[1]] as UseOnyxResult; From c669c090dd637ee639e68074f291ad68ed363a48 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Mon, 5 Jan 2026 23:27:54 +0100 Subject: [PATCH 3/9] lint --- src/hooks/useOnyx.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index bcd8b14285ec..acfbc515137e 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -97,7 +97,7 @@ const useOnyx: OriginalUseOnyx = ; + return [{...(snapshotResult[0] as object), ...(originalResult[0] as object)}, originalResult[1]] as UseOnyxResult; } if (isEmpty(snapshotResult[0])) { From 21df21dd41cc5fa92d39ed52fbf0c87c7208f05a Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 6 Jan 2026 21:28:05 +0100 Subject: [PATCH 4/9] lint --- src/hooks/useOnyx.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index acfbc515137e..52c5f888d9e8 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -97,7 +97,8 @@ const useOnyx: OriginalUseOnyx = ; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return [{...(snapshotResult[0] as Record), ...(originalResult[0] as Record)}, originalResult[1]] as UseOnyxResult; } if (isEmpty(snapshotResult[0])) { From d0b3fd48e696fead7e1b93ecdda99474c5a8532c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 6 Jan 2026 21:51:09 +0100 Subject: [PATCH 5/9] use same evictableKeys in tests --- tests/perf-test/ModifiedExpenseMessage.perf-test.ts | 8 +++++++- tests/perf-test/ReportActionCompose.perf-test.tsx | 8 +++++++- tests/perf-test/ReportActionsList.perf-test.tsx | 8 +++++++- tests/perf-test/ReportActionsUtils.perf-test.ts | 8 +++++++- tests/perf-test/ReportUtils.perf-test.ts | 11 ++++++++--- tests/perf-test/SidebarLinks.perf-test.tsx | 8 +++++++- tests/perf-test/SidebarUtils.perf-test.ts | 8 +++++++- tests/ui/ComposerTest.tsx | 8 +++++++- tests/ui/DebugReportActionsTest.tsx | 8 +++++++- tests/ui/LHNItemsPresence.tsx | 8 +++++++- tests/ui/PureReportActionItemTest.tsx | 8 +++++++- tests/ui/ReportActionComposeTest.tsx | 8 +++++++- tests/ui/ReportActionItemMessageEditTest.tsx | 8 +++++++- tests/ui/ReportAttachments.tsx | 8 +++++++- tests/ui/ReportDetailsPageTest.tsx | 8 +++++++- tests/ui/ReportListItemHeaderTest.tsx | 8 +++++++- tests/ui/TransactionItemRowRBRTest.tsx | 8 +++++++- tests/ui/WorkspaceCategoriesTest.tsx | 8 +++++++- .../components/IOURequestStepConfirmationPageTest.tsx | 8 +++++++- tests/unit/PersistedRequests.ts | 8 +++++++- tests/unit/ReportActionItemSingleTest.ts | 8 +++++++- tests/unit/ReportActionsUtilsTest.ts | 8 +++++++- tests/unit/SidebarFilterTest.ts | 8 +++++++- tests/unit/SidebarOrderTest.ts | 8 +++++++- tests/unit/SidebarTest.ts | 8 +++++++- tests/unit/SidebarUtilsTest.ts | 8 +++++++- tests/unit/TransactionGroupListItemTest.tsx | 8 +++++++- tests/unit/hooks/useShowNotFoundPageInIOUStep.test.ts | 8 +++++++- 28 files changed, 197 insertions(+), 30 deletions(-) diff --git a/tests/perf-test/ModifiedExpenseMessage.perf-test.ts b/tests/perf-test/ModifiedExpenseMessage.perf-test.ts index 56cf6553bb84..f3efcebb3a4d 100644 --- a/tests/perf-test/ModifiedExpenseMessage.perf-test.ts +++ b/tests/perf-test/ModifiedExpenseMessage.perf-test.ts @@ -14,7 +14,13 @@ import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/perf-test/ReportActionCompose.perf-test.tsx b/tests/perf-test/ReportActionCompose.perf-test.tsx index 92c7b77456e8..6c08ec241707 100644 --- a/tests/perf-test/ReportActionCompose.perf-test.tsx +++ b/tests/perf-test/ReportActionCompose.perf-test.tsx @@ -69,7 +69,13 @@ jest.mock('@src/libs/actions/EmojiPickerAction', () => { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/perf-test/ReportActionsList.perf-test.tsx b/tests/perf-test/ReportActionsList.perf-test.tsx index b1b251f352c8..cced1b7a4a43 100644 --- a/tests/perf-test/ReportActionsList.perf-test.tsx +++ b/tests/perf-test/ReportActionsList.perf-test.tsx @@ -63,7 +63,13 @@ jest.mock('@src/components/ConfirmedRoute.tsx'); beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/perf-test/ReportActionsUtils.perf-test.ts b/tests/perf-test/ReportActionsUtils.perf-test.ts index 5bb102f86ac9..796b0cb279e0 100644 --- a/tests/perf-test/ReportActionsUtils.perf-test.ts +++ b/tests/perf-test/ReportActionsUtils.perf-test.ts @@ -40,7 +40,13 @@ describe('ReportActionsUtils', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); Onyx.multiSet({ diff --git a/tests/perf-test/ReportUtils.perf-test.ts b/tests/perf-test/ReportUtils.perf-test.ts index 574d1867adec..43fa15db7b28 100644 --- a/tests/perf-test/ReportUtils.perf-test.ts +++ b/tests/perf-test/ReportUtils.perf-test.ts @@ -9,8 +9,7 @@ import { getDisplayNamesWithTooltips, getIcons, getIconsForParticipants, - getIOUReportActionDisplayMessage, - // Will be fixed in https://github.com/Expensify/App/issues/76852 + getIOUReportActionDisplayMessage, // Will be fixed in https://github.com/Expensify/App/issues/76852 // eslint-disable-next-line @typescript-eslint/no-deprecated getReportName, getReportPreviewMessage, @@ -66,7 +65,13 @@ describe('ReportUtils', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/perf-test/SidebarLinks.perf-test.tsx b/tests/perf-test/SidebarLinks.perf-test.tsx index cb23968dd2db..cc71dce80c47 100644 --- a/tests/perf-test/SidebarLinks.perf-test.tsx +++ b/tests/perf-test/SidebarLinks.perf-test.tsx @@ -54,7 +54,13 @@ describe('SidebarLinks', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/perf-test/SidebarUtils.perf-test.ts b/tests/perf-test/SidebarUtils.perf-test.ts index 9c1db3ad522c..399c26059e42 100644 --- a/tests/perf-test/SidebarUtils.perf-test.ts +++ b/tests/perf-test/SidebarUtils.perf-test.ts @@ -54,7 +54,13 @@ describe('SidebarUtils', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); Onyx.multiSet({ diff --git a/tests/ui/ComposerTest.tsx b/tests/ui/ComposerTest.tsx index aa94ca2e8176..75dda6cdcbb1 100644 --- a/tests/ui/ComposerTest.tsx +++ b/tests/ui/ComposerTest.tsx @@ -15,7 +15,13 @@ describe('Composer', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/ui/DebugReportActionsTest.tsx b/tests/ui/DebugReportActionsTest.tsx index a72df0a538ec..e1c607fa2870 100644 --- a/tests/ui/DebugReportActionsTest.tsx +++ b/tests/ui/DebugReportActionsTest.tsx @@ -29,7 +29,13 @@ describe('DebugReportActions', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); act(() => { Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.EN); diff --git a/tests/ui/LHNItemsPresence.tsx b/tests/ui/LHNItemsPresence.tsx index 6fb7cfea6e41..12ffec28a5c3 100644 --- a/tests/ui/LHNItemsPresence.tsx +++ b/tests/ui/LHNItemsPresence.tsx @@ -127,7 +127,13 @@ describe('SidebarLinksData', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); initOnyxDerivedValues(); }); diff --git a/tests/ui/PureReportActionItemTest.tsx b/tests/ui/PureReportActionItemTest.tsx index 1712ee3621c5..55fc6bf2c739 100644 --- a/tests/ui/PureReportActionItemTest.tsx +++ b/tests/ui/PureReportActionItemTest.tsx @@ -49,7 +49,13 @@ describe('PureReportActionItem', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); jest.spyOn(NativeNavigation, 'useRoute').mockReturnValue({key: '', name: ''}); jest.spyOn(ReportActionUtils, 'getIOUActionForReportID').mockImplementation(getIOUActionForReportID); diff --git a/tests/ui/ReportActionComposeTest.tsx b/tests/ui/ReportActionComposeTest.tsx index ec840b47c019..95265e9e0b85 100644 --- a/tests/ui/ReportActionComposeTest.tsx +++ b/tests/ui/ReportActionComposeTest.tsx @@ -73,7 +73,13 @@ describe('ReportActionCompose Integration Tests', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/ui/ReportActionItemMessageEditTest.tsx b/tests/ui/ReportActionItemMessageEditTest.tsx index 868b555d35f7..7e33a86b1689 100644 --- a/tests/ui/ReportActionItemMessageEditTest.tsx +++ b/tests/ui/ReportActionItemMessageEditTest.tsx @@ -73,7 +73,13 @@ describe('ReportActionCompose Integration Tests', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/ui/ReportAttachments.tsx b/tests/ui/ReportAttachments.tsx index 7aae70f2e69c..9ff9a9ff23d3 100644 --- a/tests/ui/ReportAttachments.tsx +++ b/tests/ui/ReportAttachments.tsx @@ -142,7 +142,13 @@ describe('ReportAttachments', () => { [ONYXKEYS.SESSION]: {accountID: TEST_USER_ACCOUNT_ID, email: TEST_USER_LOGIN}, [ONYXKEYS.PERSONAL_DETAILS_LIST]: {[TEST_USER_ACCOUNT_ID]: {accountID: TEST_USER_ACCOUNT_ID, login: TEST_USER_LOGIN}}, }, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); beforeEach(async () => { diff --git a/tests/ui/ReportDetailsPageTest.tsx b/tests/ui/ReportDetailsPageTest.tsx index 7ce8c495292d..39475b158918 100644 --- a/tests/ui/ReportDetailsPageTest.tsx +++ b/tests/ui/ReportDetailsPageTest.tsx @@ -33,7 +33,13 @@ describe('ReportDetailsPage', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/ui/ReportListItemHeaderTest.tsx b/tests/ui/ReportListItemHeaderTest.tsx index d77eb05b4764..63aff6a02795 100644 --- a/tests/ui/ReportListItemHeaderTest.tsx +++ b/tests/ui/ReportListItemHeaderTest.tsx @@ -113,7 +113,13 @@ describe('ReportListItemHeader', () => { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/ui/TransactionItemRowRBRTest.tsx b/tests/ui/TransactionItemRowRBRTest.tsx index dbeb56147238..4540fcccf876 100644 --- a/tests/ui/TransactionItemRowRBRTest.tsx +++ b/tests/ui/TransactionItemRowRBRTest.tsx @@ -95,7 +95,13 @@ describe('TransactionItemRowRBR', () => { beforeAll(async () => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); await Onyx.set(ONYXKEYS.NVP_PREFERRED_LOCALE, CONST.LOCALES.DEFAULT); }); diff --git a/tests/ui/WorkspaceCategoriesTest.tsx b/tests/ui/WorkspaceCategoriesTest.tsx index e12e4ab49f8f..e0fb040f8d80 100644 --- a/tests/ui/WorkspaceCategoriesTest.tsx +++ b/tests/ui/WorkspaceCategoriesTest.tsx @@ -53,7 +53,13 @@ describe('WorkspaceCategories', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx index ace02cde0617..924638d72473 100644 --- a/tests/ui/components/IOURequestStepConfirmationPageTest.tsx +++ b/tests/ui/components/IOURequestStepConfirmationPageTest.tsx @@ -200,7 +200,13 @@ describe('IOURequestStepConfirmationPageTest', () => { jest.clearAllMocks(); Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); diff --git a/tests/unit/PersistedRequests.ts b/tests/unit/PersistedRequests.ts index 1c1b3c552c15..2f685551dc2d 100644 --- a/tests/unit/PersistedRequests.ts +++ b/tests/unit/PersistedRequests.ts @@ -15,7 +15,13 @@ const request: Request = { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/unit/ReportActionItemSingleTest.ts b/tests/unit/ReportActionItemSingleTest.ts index 8d400c96b510..d4591fb56d65 100644 --- a/tests/unit/ReportActionItemSingleTest.ts +++ b/tests/unit/ReportActionItemSingleTest.ts @@ -12,7 +12,13 @@ describe('ReportActionItemSingle', () => { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 839911a4822f..901d994998af 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -30,7 +30,13 @@ describe('ReportActionsUtils', () => { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/unit/SidebarFilterTest.ts b/tests/unit/SidebarFilterTest.ts index 113d16fec0b4..8c3fbbe93473 100644 --- a/tests/unit/SidebarFilterTest.ts +++ b/tests/unit/SidebarFilterTest.ts @@ -33,7 +33,13 @@ xdescribe('Sidebar', () => { beforeAll(() => Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }), ); diff --git a/tests/unit/SidebarOrderTest.ts b/tests/unit/SidebarOrderTest.ts index 1495753ee357..023df51c0d6a 100644 --- a/tests/unit/SidebarOrderTest.ts +++ b/tests/unit/SidebarOrderTest.ts @@ -57,7 +57,13 @@ describe('Sidebar', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); initOnyxDerivedValues(); IntlStore.load(CONST.LOCALES.EN); diff --git a/tests/unit/SidebarTest.ts b/tests/unit/SidebarTest.ts index 3f2fa09cfd8b..2bea14b68f69 100644 --- a/tests/unit/SidebarTest.ts +++ b/tests/unit/SidebarTest.ts @@ -24,7 +24,13 @@ describe('Sidebar', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); initOnyxDerivedValues(); diff --git a/tests/unit/SidebarUtilsTest.ts b/tests/unit/SidebarUtilsTest.ts index a417d1dc3451..89ce35853274 100644 --- a/tests/unit/SidebarUtilsTest.ts +++ b/tests/unit/SidebarUtilsTest.ts @@ -40,7 +40,13 @@ describe('SidebarUtils', () => { beforeAll(async () => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); IntlStore.load(CONST.LOCALES.EN); initOnyxDerivedValues(); diff --git a/tests/unit/TransactionGroupListItemTest.tsx b/tests/unit/TransactionGroupListItemTest.tsx index 0a3dc1ebb35e..3a67d2abb561 100644 --- a/tests/unit/TransactionGroupListItemTest.tsx +++ b/tests/unit/TransactionGroupListItemTest.tsx @@ -156,7 +156,13 @@ describe('TransactionGroupListItem', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); jest.spyOn(NativeNavigation, 'useRoute').mockReturnValue({key: '', name: ''}); }); diff --git a/tests/unit/hooks/useShowNotFoundPageInIOUStep.test.ts b/tests/unit/hooks/useShowNotFoundPageInIOUStep.test.ts index 840270d59578..037579a600a0 100644 --- a/tests/unit/hooks/useShowNotFoundPageInIOUStep.test.ts +++ b/tests/unit/hooks/useShowNotFoundPageInIOUStep.test.ts @@ -12,7 +12,13 @@ describe('useShowNotFoundPageInIOUStep', () => { beforeAll(() => { Onyx.init({ keys: ONYXKEYS, - evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS], + evictableKeys: [ + ONYXKEYS.COLLECTION.REPORT_ACTIONS, + ONYXKEYS.COLLECTION.SNAPSHOT, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_DRAFTS, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES, + ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS, + ], }); }); From 3e770f5eedb8278f813b40705fd0a7589c4e830c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 6 Jan 2026 22:12:10 +0100 Subject: [PATCH 6/9] ts --- tests/unit/SidebarFilterTest.ts | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/unit/SidebarFilterTest.ts b/tests/unit/SidebarFilterTest.ts index 8c3fbbe93473..4ebbe5804cbd 100644 --- a/tests/unit/SidebarFilterTest.ts +++ b/tests/unit/SidebarFilterTest.ts @@ -4,6 +4,7 @@ import DateUtils from '@libs/DateUtils'; import CONST from '@src/CONST'; import type {Report} from '@src/types/onyx'; import type {ReportCollectionDataSet} from '@src/types/onyx/Report'; +import ONYXKEYS from '../../src/ONYXKEYS'; import * as LHNTestUtils from '../utils/LHNTestUtils'; import {getNavigateToChatHintRegex, translateLocal} from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; @@ -13,21 +14,6 @@ import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatch // during the test depend on its methods. jest.mock('@libs/Permissions'); -const ONYXKEYS = { - PERSONAL_DETAILS_LIST: 'personalDetailsList', - IS_LOADING_APP: 'isLoadingApp', - NVP_PRIORITY_MODE: 'nvp_priorityMode', - SESSION: 'session', - BETAS: 'betas', - COLLECTION: { - REPORT: 'report_', - REPORT_ACTIONS: 'reportActions_', - POLICY: 'policy_', - REPORT_DRAFT_COMMENT: 'reportDraftComment_', - }, - NETWORK: 'network', -} as const; - // We need to fix this test as a follow up. There seems to be some problems with memory after filtering got more complicated. xdescribe('Sidebar', () => { beforeAll(() => From 0a610963ebb0c8ce5ce9b1029d7e1c5d1056e16f Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 6 Jan 2026 22:17:13 +0100 Subject: [PATCH 7/9] prettier --- tests/perf-test/ReportUtils.perf-test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/perf-test/ReportUtils.perf-test.ts b/tests/perf-test/ReportUtils.perf-test.ts index 43fa15db7b28..1ccb8e075f26 100644 --- a/tests/perf-test/ReportUtils.perf-test.ts +++ b/tests/perf-test/ReportUtils.perf-test.ts @@ -9,7 +9,8 @@ import { getDisplayNamesWithTooltips, getIcons, getIconsForParticipants, - getIOUReportActionDisplayMessage, // Will be fixed in https://github.com/Expensify/App/issues/76852 + getIOUReportActionDisplayMessage, + // Will be fixed in https://github.com/Expensify/App/issues/76852 // eslint-disable-next-line @typescript-eslint/no-deprecated getReportName, getReportPreviewMessage, From 7cadd3cbdf9824ac8b84075b547b5520fdd768c8 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:07:09 +0100 Subject: [PATCH 8/9] set initWithStoredValues and allowStaleData to minimize connection overhead --- src/hooks/useOnyx.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index 52c5f888d9e8..4f108b295a15 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -70,7 +70,7 @@ const useOnyx: OriginalUseOnyx = { @@ -89,6 +89,8 @@ const useOnyx: OriginalUseOnyx = Date: Tue, 13 Jan 2026 21:25:05 +0100 Subject: [PATCH 9/9] use hook conditionally The condition must never change in any react component lifecycle, otherwise this would cause weird bugs --- src/hooks/useOnyx.ts | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/hooks/useOnyx.ts b/src/hooks/useOnyx.ts index 4f108b295a15..7bc0e5042c75 100644 --- a/src/hooks/useOnyx.ts +++ b/src/hooks/useOnyx.ts @@ -67,33 +67,17 @@ const useOnyx: OriginalUseOnyx = { - if (!shouldUseSnapshot) { - return () => false; - } - if (!selector) { return (data: OnyxValue | undefined) => getKeyData(data as SearchResults, key) as OnyxValue; } return (data: OnyxValue | undefined) => selector(getKeyData(data as SearchResults, key)); - }, [shouldUseSnapshot, selector, key]); - const snapshotOnyxOptions: UseOnyxOptions> = { - ...optionsWithoutSelector, - selector: snapshotSelector, - allowDynamicKey: true, - canBeMissing: shouldUseSnapshot ? optionsWithoutSelector.canBeMissing : true, - initWithStoredValues: shouldUseSnapshot ? optionsWithoutSelector.initWithStoredValues : false, - allowStaleData: shouldUseSnapshot ? optionsWithoutSelector.allowStaleData : true, - }; + }, [selector, key]); + const snapshotOnyxOptions: UseOnyxOptions> = {...optionsWithoutSelector, selector: snapshotSelector, allowDynamicKey: true}; const snapshotKey = `${ONYXKEYS.COLLECTION.SNAPSHOT}${currentSearchHash}` as OnyxKey; - const snapshotResult = originalUseOnyx(snapshotKey, snapshotOnyxOptions, dependencies); + const snapshotResult = shouldUseSnapshot ? originalUseOnyx(snapshotKey, snapshotOnyxOptions, dependencies) : [undefined, {status: 'loaded'}]; const result = useMemo((): UseOnyxResult => { // Merge snapshot data with live data if possible