diff --git a/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx b/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx
index 8646f103ef01..f3739c106841 100644
--- a/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx
+++ b/src/components/MoneyRequestReportView/MoneyRequestReportNavigation.tsx
@@ -2,7 +2,9 @@ import React, {useEffect, useState} from 'react';
 import {View} from 'react-native';
 import type {OnyxEntry} from 'react-native-onyx';
 import PrevNextButtons from '@components/PrevNextButtons';
+import {useSearchStateContext} from '@components/Search/SearchContext';
 import Text from '@components/Text';
+import useFilterPendingDeleteReports from '@hooks/useFilterPendingDeleteReports';
 import useOnyx from '@hooks/useOnyx';
 import useSearchSections from '@hooks/useSearchSections';
 import useThemeStyles from '@hooks/useThemeStyles';
@@ -20,6 +22,12 @@ type MoneyRequestReportNavigationProps = {
     shouldDisplayNarrowVersion: boolean;
 };
 
+type MoneyRequestReportNavigationContentProps = MoneyRequestReportNavigationProps & {
+    allReports: Array<string | undefined>;
+    isSearchLoading: boolean;
+    lastSearchQuery: OnyxEntry<LastSearchParams>;
+};
+
 type SnapshotGuard = {
     hasMultiple: boolean;
     includesReport: boolean;
@@ -71,8 +79,7 @@ const buildSnapshotGuardSelector =
         return {hasMultiple: count > 1, includesReport};
     };
 
-function MoneyRequestReportNavigationInner({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) {
-    const {allReports, isSearchLoading, lastSearchQuery} = useSearchSections();
+function MoneyRequestReportNavigationContent({reportID, shouldDisplayNarrowVersion, allReports, isSearchLoading, lastSearchQuery}: MoneyRequestReportNavigationContentProps) {
     const styles = useThemeStyles();
 
     const liveCurrentIndex = allReports.indexOf(reportID);
@@ -192,19 +199,43 @@ function MoneyRequestReportNavigationInner({reportID, shouldDisplayNarrowVersion
     );
 }
 
+// All Onyx subscriptions via useSearchSections. Mounts if there are no sorted report IDs in the context.
+function MoneyRequestReportNavigationStandalone({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) {
+    const {allReports, isSearchLoading, lastSearchQuery} = useSearchSections();
+
+    return (
+        <MoneyRequestReportNavigationContent
+            reportID={reportID}
+            shouldDisplayNarrowVersion={shouldDisplayNarrowVersion}
+            allReports={allReports}
+            isSearchLoading={isSearchLoading}
+            lastSearchQuery={lastSearchQuery}
+        />
+    );
+}
+
 function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: MoneyRequestReportNavigationProps) {
+    // Guard: only mount inner tree when snapshot confirms multiple expense reports
     const [isExpenseReportSearch] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY, {selector: selectIsExpenseReportSearch});
     const [hash] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY, {selector: selectQueryHash});
     const snapshotGuardSelector = buildSnapshotGuardSelector(reportID);
     const [snapshotGuard = EMPTY_GUARD] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, {selector: snapshotGuardSelector});
 
+    // Fast-path hooks (always called to satisfy rules of hooks)
+    const {sortedReportIDs} = useSearchStateContext();
+    const [lastSearchQuery] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY);
+    const searchLoadingSelector = (data: OnyxEntry<SearchResults>) => !!data?.search?.isLoading;
+    const [isSearchLoading = false] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${lastSearchQuery?.queryJSON?.hash}`, {
+        selector: searchLoadingSelector,
+    });
+    const allReports = useFilterPendingDeleteReports(sortedReportIDs);
+
     const isLiveGuardSatisfied = isExpenseReportSearch && snapshotGuard.hasMultiple && snapshotGuard.includesReport;
 
     // Once the live snapshot has satisfied the guard during this mount, keep the inner component
     // mounted even if the guard later flips false (e.g. the current report is removed from the
     // snapshot after approving it). The inner component falls back to a cached list so the
-    // carousel stays visible for continued navigation. setState during render is the React-
-    // recommended pattern for storing information from previous renders.
+    // carousel stays visible for continued navigation.
     const [shouldKeepMounted, setShouldKeepMounted] = useState(false);
     if (isLiveGuardSatisfied && !shouldKeepMounted) {
         setShouldKeepMounted(true);
@@ -214,8 +245,22 @@ function MoneyRequestReportNavigation({reportID, shouldDisplayNarrowVersion}: Mo
         return null;
     }
 
+    // Fast path: use pre-computed IDs from context when available and no pagination is in flight.
+    // During pagination fall back to full subscription so new pages are reflected immediately.
+    if (allReports.length > 0 && !isSearchLoading) {
+        return (
+            <MoneyRequestReportNavigationContent
+                reportID={reportID}
+                shouldDisplayNarrowVersion={shouldDisplayNarrowVersion}
+                allReports={allReports}
+                isSearchLoading={isSearchLoading}
+                lastSearchQuery={lastSearchQuery}
+            />
+        );
+    }
+
     return (
-        <MoneyRequestReportNavigationInner
+        <MoneyRequestReportNavigationStandalone
             reportID={reportID}
             shouldDisplayNarrowVersion={shouldDisplayNarrowVersion}
         />
diff --git a/src/components/Search/SearchContext.tsx b/src/components/Search/SearchContext.tsx
index c3cb96349aa5..2f3a2bc8e7e5 100644
--- a/src/components/Search/SearchContext.tsx
+++ b/src/components/Search/SearchContext.tsx
@@ -55,6 +55,7 @@ const defaultSearchContextData: SearchContextData = {
     currentSearchHash: -1,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as Record<SearchKey, SearchTypeMenuItem>,
+    sortedReportIDs: CONST.EMPTY_ARRAY,
 };
 
 const defaultSearchStateContext: SearchStateContextValue = {
@@ -77,6 +78,7 @@ const defaultSearchActionsContext: SearchActionsContextValue = {
     setShouldShowSelectAllMatchingItems: () => {},
     selectAllMatchingItems: () => {},
     setShouldResetSearchQuery: () => {},
+    setSortedReportIDs: () => {},
 };
 
 const SearchStateContext = React.createContext<SearchStateContextValue>(defaultSearchStateContext);
@@ -316,6 +318,15 @@ function SearchContextProvider({children}: SearchContextProps) {
         }));
     };
 
+    const setSortedReportIDs = (newIDs: ReadonlyArray<string | undefined>) => {
+        setSearchContextData((prev) => {
+            // ensure that we don't save the same report IDs unless they are really different
+            const hasChanged = prev.sortedReportIDs.length !== newIDs.length || prev.sortedReportIDs.some((id, i) => id !== newIDs.at(i));
+
+            return hasChanged ? {...prev, sortedReportIDs: newIDs} : prev;
+        });
+    };
+
     const searchStateContextValue: SearchStateContextValue = {
         ...searchContextData,
         suggestedSearches,
@@ -342,6 +353,7 @@ function SearchContextProvider({children}: SearchContextProps) {
         setShouldShowSelectAllMatchingItems,
         selectAllMatchingItems,
         setShouldResetSearchQuery,
+        setSortedReportIDs,
     };
 
     return (
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index db66d401a73e..fefeffb47585 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -24,6 +24,7 @@ import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
 import usePrevious from '@hooks/usePrevious';
 import useReportAttributes from '@hooks/useReportAttributes';
 import useResponsiveLayout from '@hooks/useResponsiveLayout';
+import useSaveSortedReportIDs from '@hooks/useSaveSortedReportIDs';
 import useSearchHighlightAndScroll from '@hooks/useSearchHighlightAndScroll';
 import useSearchShouldCalculateTotals from '@hooks/useSearchShouldCalculateTotals';
 import useStableArrayReference from '@hooks/useStableArrayReference';
@@ -1286,6 +1287,8 @@ function Search({
         [type, status, filteredData, localeCompare, translate, sortBy, sortOrder, validGroupBy, isChat, newSearchResultKeys, hash],
     );
 
+    useSaveSortedReportIDs(type, sortedData);
+
     const {stableSortedData, hasCachedOptimisticItem} = useStableOptimisticSortedData(sortedData, searchResults, optimisticTrackingState);
 
     useEffect(() => {
diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts
index b402cfd6ab0a..5687cac135a2 100644
--- a/src/components/Search/types.ts
+++ b/src/components/Search/types.ts
@@ -180,6 +180,7 @@ type SearchContextData = {
     isOnSearch: boolean;
     shouldTurnOffSelectionMode: boolean;
     shouldResetSearchQuery: boolean;
+    sortedReportIDs: ReadonlyArray<string | undefined>;
     /** True when at least one transaction is selected. */
     hasSelectedTransactions: boolean;
 };
@@ -212,6 +213,7 @@ type SearchActionsContextValue = {
     setShouldShowSelectAllMatchingItems: (shouldShow: boolean) => void;
     selectAllMatchingItems: (on: boolean) => void;
     setShouldResetSearchQuery: (shouldReset: boolean) => void;
+    setSortedReportIDs: (ids: ReadonlyArray<string | undefined>) => void;
 };
 
 type ASTNode = {
diff --git a/src/hooks/useFilterPendingDeleteReports.ts b/src/hooks/useFilterPendingDeleteReports.ts
new file mode 100644
index 000000000000..fa457f622466
--- /dev/null
+++ b/src/hooks/useFilterPendingDeleteReports.ts
@@ -0,0 +1,39 @@
+import type {OnyxCollection} from 'react-native-onyx';
+import {isReportPendingDelete} from '@libs/ReportUtils';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report} from '@src/types/onyx';
+import useOnyx from './useOnyx';
+
+/**
+ * Returns sorted keys of reports pending deletion.
+ * Sorted string[] keeps Onyx comparison cheap (PERF-11).
+ */
+const selectPendingDeleteReportKeys = (reports: OnyxCollection<Report>): string[] => {
+    const keys: string[] = [];
+    for (const [key, report] of Object.entries(reports ?? {})) {
+        if (isReportPendingDelete(report)) {
+            keys.push(key);
+        }
+    }
+    return keys.sort();
+};
+
+/**
+ * Filters out report IDs whose corresponding reports have a pending DELETE action.
+ * Subscribes to the REPORT collection with a lightweight selector to minimize re-renders.
+ */
+function useFilterPendingDeleteReports(ids: ReadonlyArray<string | undefined>): Array<string | undefined> {
+    const [pendingDeleteReportKeys = CONST.EMPTY_ARRAY] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: selectPendingDeleteReportKeys});
+    const pendingDeleteReportKeysSet = new Set(pendingDeleteReportKeys);
+
+    return ids.filter((id) => {
+        if (!id) {
+            return false;
+        }
+        return !pendingDeleteReportKeysSet.has(`${ONYXKEYS.COLLECTION.REPORT}${id}`);
+    });
+}
+
+export {selectPendingDeleteReportKeys};
+export default useFilterPendingDeleteReports;
diff --git a/src/hooks/useSaveSortedReportIDs.ts b/src/hooks/useSaveSortedReportIDs.ts
new file mode 100644
index 000000000000..17626ed0d327
--- /dev/null
+++ b/src/hooks/useSaveSortedReportIDs.ts
@@ -0,0 +1,30 @@
+import {useEffect} from 'react';
+import {useSearchActionsContext} from '@components/Search/SearchContext';
+import CONST from '@src/CONST';
+import type {SearchDataTypes} from '@src/types/onyx/SearchResults';
+
+/**
+ * Persists sorted report IDs to Search context so that MoneyRequestReportNavigation
+ * can read them without recomputing getSortedSections.
+ * Only stores IDs for expense-report searches; clears the context for all other types
+ * to force the fallback computation in the navigation header.
+ */
+function useSaveSortedReportIDs(type: SearchDataTypes, items: Array<{reportID?: string | undefined}>) {
+    const {setSortedReportIDs} = useSearchActionsContext();
+
+    useEffect(() => {
+        // Only expense-report searches produce report-level IDs suitable for navigation arrows.
+        // For all other types (expense, invoice, etc.) the items are transaction-level and share
+        // reportIDs, so we clear the context to force the fallback computation in navigation.
+        if (type !== CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT) {
+            setSortedReportIDs([]);
+            return;
+        }
+
+        const reportIDs = items.map((item) => item.reportID);
+
+        setSortedReportIDs(reportIDs);
+    }, [type, items, setSortedReportIDs]);
+}
+
+export default useSaveSortedReportIDs;
diff --git a/src/hooks/useSearchSections.ts b/src/hooks/useSearchSections.ts
index 31cb3eca0a35..7c1f1d012377 100644
--- a/src/hooks/useSearchSections.ts
+++ b/src/hooks/useSearchSections.ts
@@ -1,32 +1,17 @@
-import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
-import {isReportPendingDelete, selectFilteredReportActions} from '@libs/ReportUtils';
+import type {OnyxEntry} from 'react-native-onyx';
+import {selectFilteredReportActions} from '@libs/ReportUtils';
 import {getSections, getSortedSections} from '@libs/SearchUIUtils';
-import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Report} from '@src/types/onyx';
 import type LastSearchParams from '@src/types/onyx/ReportNavigation';
 import useActionLoadingReportIDs from './useActionLoadingReportIDs';
 import useArchivedReportsIdSet from './useArchivedReportsIdSet';
 import {useCurrencyListActions} from './useCurrencyList';
 import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
+import useFilterPendingDeleteReports, {selectPendingDeleteReportKeys} from './useFilterPendingDeleteReports';
 import useLocalize from './useLocalize';
 import useOnyx from './useOnyx';
 import useReportAttributes from './useReportAttributes';
 
-/**
- * Returns sorted keys of reports pending deletion.
- * Sorted string[] keeps Onyx comparison cheap (PERF-11).
- */
-const selectPendingDeleteReportKeys = (reports: OnyxCollection<Report>): string[] => {
-    const keys: string[] = [];
-    for (const [key, report] of Object.entries(reports ?? {})) {
-        if (isReportPendingDelete(report)) {
-            keys.push(key);
-        }
-    }
-    return keys.sort();
-};
-
 type UseSearchSectionsResult = {
     allReports: Array<string | undefined>;
     isSearchLoading: boolean;
@@ -36,8 +21,6 @@ type UseSearchSectionsResult = {
 function useSearchSections(): UseSearchSectionsResult {
     const [lastSearchQuery] = useOnyx(ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY);
     const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${lastSearchQuery?.queryJSON?.hash}`);
-    const [pendingDeleteReportKeys = CONST.EMPTY_ARRAY] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: selectPendingDeleteReportKeys});
-    const pendingDeleteReportKeysSet = new Set(pendingDeleteReportKeys);
     const currentUserDetails = useCurrentUserPersonalDetails();
     const {localeCompare, formatPhoneNumber, translate} = useLocalize();
     const isActionLoadingSet = useActionLoadingReportIDs();
@@ -86,14 +69,7 @@ function useSearchSections(): UseSearchSectionsResult {
         results = getSortedSections(type, status ?? '', searchData, localeCompare, translate, sortBy, sortOrder, groupBy).map((value) => value.reportID);
     }
 
-    const allReports = results.filter((id) => {
-        if (!id) {
-            return false;
-        }
-        return !pendingDeleteReportKeysSet.has(`${ONYXKEYS.COLLECTION.REPORT}${id}`);
-    });
-
-    return {allReports, isSearchLoading: !!currentSearchResults?.search?.isLoading, lastSearchQuery};
+    return {allReports: useFilterPendingDeleteReports(results), isSearchLoading: !!currentSearchResults?.search?.isLoading, lastSearchQuery};
 }
 
 export {selectPendingDeleteReportKeys};
diff --git a/tests/ui/CategoryListItemHeaderTest.tsx b/tests/ui/CategoryListItemHeaderTest.tsx
index 6931285b8051..355e82517a0b 100644
--- a/tests/ui/CategoryListItemHeaderTest.tsx
+++ b/tests/ui/CategoryListItemHeaderTest.tsx
@@ -41,6 +41,7 @@ const mockSearchStateContext = {
     shouldUseLiveData: false,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as SearchStateContextValue['suggestedSearches'],
+    sortedReportIDs: [],
     hasSelectedTransactions: false,
 } satisfies SearchStateContextValue;
 
@@ -54,6 +55,7 @@ const mockSearchActionsContext = {
     setShouldShowSelectAllMatchingItems: jest.fn(),
     selectAllMatchingItems: jest.fn(),
     setShouldResetSearchQuery: jest.fn(),
+    setSortedReportIDs: jest.fn(),
 } satisfies SearchActionsContextValue;
 
 const createCategoryListItem = (category: string, options: Partial<TransactionCategoryGroupListItemType> = {}): TransactionCategoryGroupListItemType => ({
diff --git a/tests/ui/MerchantListItemHeaderTest.tsx b/tests/ui/MerchantListItemHeaderTest.tsx
index b7ac8ee1c4f9..6e8bb26f4f4c 100644
--- a/tests/ui/MerchantListItemHeaderTest.tsx
+++ b/tests/ui/MerchantListItemHeaderTest.tsx
@@ -41,6 +41,7 @@ const mockSearchStateContext = {
     shouldUseLiveData: false,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as SearchStateContextValue['suggestedSearches'],
+    sortedReportIDs: [],
     hasSelectedTransactions: false,
 } satisfies SearchStateContextValue;
 
@@ -54,6 +55,7 @@ const mockSearchActionsContext = {
     setShouldShowSelectAllMatchingItems: jest.fn(),
     selectAllMatchingItems: jest.fn(),
     setShouldResetSearchQuery: jest.fn(),
+    setSortedReportIDs: jest.fn(),
 } satisfies SearchActionsContextValue;
 
 const createMerchantListItem = (merchant: string, options: Partial<TransactionMerchantGroupListItemType> = {}): TransactionMerchantGroupListItemType => ({
diff --git a/tests/ui/MonthListItemHeaderTest.tsx b/tests/ui/MonthListItemHeaderTest.tsx
index 9f5fda8c521a..84bdae31886a 100644
--- a/tests/ui/MonthListItemHeaderTest.tsx
+++ b/tests/ui/MonthListItemHeaderTest.tsx
@@ -41,6 +41,7 @@ const mockSearchStateContext = {
     shouldUseLiveData: false,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as SearchStateContextValue['suggestedSearches'],
+    sortedReportIDs: [],
     hasSelectedTransactions: false,
 } satisfies SearchStateContextValue;
 
@@ -54,6 +55,7 @@ const mockSearchActionsContext = {
     setShouldShowSelectAllMatchingItems: jest.fn(),
     selectAllMatchingItems: jest.fn(),
     setShouldResetSearchQuery: jest.fn(),
+    setSortedReportIDs: jest.fn(),
 } satisfies SearchActionsContextValue;
 
 const createMonthListItem = (year: number, month: number, options: Partial<TransactionMonthGroupListItemType> = {}): TransactionMonthGroupListItemType => ({
diff --git a/tests/ui/WeekListItemHeaderTest.tsx b/tests/ui/WeekListItemHeaderTest.tsx
index d87789e1428f..7447eb0cb750 100644
--- a/tests/ui/WeekListItemHeaderTest.tsx
+++ b/tests/ui/WeekListItemHeaderTest.tsx
@@ -40,6 +40,7 @@ const mockSearchStateContext = {
     shouldUseLiveData: false,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as SearchStateContextValue['suggestedSearches'],
+    sortedReportIDs: [],
     hasSelectedTransactions: false,
 } satisfies SearchStateContextValue;
 
@@ -53,6 +54,7 @@ const mockSearchActionsContext = {
     setShouldShowSelectAllMatchingItems: jest.fn(),
     selectAllMatchingItems: jest.fn(),
     setShouldResetSearchQuery: jest.fn(),
+    setSortedReportIDs: jest.fn(),
 } satisfies SearchActionsContextValue;
 
 const createWeekListItem = (week: string, options: Partial<TransactionWeekGroupListItemType> = {}): TransactionWeekGroupListItemType => ({
diff --git a/tests/ui/YearListItemHeaderTest.tsx b/tests/ui/YearListItemHeaderTest.tsx
index 5483298246c0..f20ee9ee12b4 100644
--- a/tests/ui/YearListItemHeaderTest.tsx
+++ b/tests/ui/YearListItemHeaderTest.tsx
@@ -41,6 +41,7 @@ const mockSearchStateContext = {
     shouldUseLiveData: false,
     currentSimilarSearchHash: -1,
     suggestedSearches: {} as SearchStateContextValue['suggestedSearches'],
+    sortedReportIDs: [],
     hasSelectedTransactions: false,
 } satisfies SearchStateContextValue;
 
@@ -54,6 +55,7 @@ const mockSearchActionsContext = {
     setShouldShowSelectAllMatchingItems: jest.fn(),
     selectAllMatchingItems: jest.fn(),
     setShouldResetSearchQuery: jest.fn(),
+    setSortedReportIDs: jest.fn(),
 } satisfies SearchActionsContextValue;
 
 const createYearListItem = (year: number, options: Partial<TransactionYearGroupListItemType> = {}): TransactionYearGroupListItemType => ({
diff --git a/tests/unit/components/MoneyRequestReportNavigation.test.tsx b/tests/unit/components/MoneyRequestReportNavigation.test.tsx
new file mode 100644
index 000000000000..1b2475d95681
--- /dev/null
+++ b/tests/unit/components/MoneyRequestReportNavigation.test.tsx
@@ -0,0 +1,104 @@
+import {renderHook} from '@testing-library/react-native';
+import {useSearchStateContext} from '@components/Search/SearchContext';
+import useFilterPendingDeleteReports from '@hooks/useFilterPendingDeleteReports';
+import CONST from '@src/CONST';
+
+/**
+ * These tests verify the routing logic of MoneyRequestReportNavigation
+ * without rendering the full component tree.
+ * They do so by testing the hooks that drive the two paths.
+ */
+
+let mockSortedReportIDs: ReadonlyArray<string | undefined> = CONST.EMPTY_ARRAY;
+
+jest.mock('@components/Search/SearchContext', () => ({
+    useSearchStateContext: () => ({sortedReportIDs: mockSortedReportIDs}),
+}));
+
+const mockUseOnyx = jest.fn();
+jest.mock('@hooks/useOnyx', () => ({
+    __esModule: true,
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+    default: (...args: unknown[]) => mockUseOnyx(...args),
+}));
+
+const mockUseSearchSections = jest.fn();
+jest.mock('@hooks/useSearchSections', () => ({
+    __esModule: true,
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+    default: () => mockUseSearchSections(),
+}));
+
+jest.mock('@hooks/useFilterPendingDeleteReports', () => ({
+    __esModule: true,
+    default: (ids: ReadonlyArray<string | undefined>) => ids.filter(Boolean),
+}));
+
+describe('MoneyRequestReportNavigation', () => {
+    beforeEach(() => {
+        mockSortedReportIDs = CONST.EMPTY_ARRAY;
+        mockUseOnyx.mockReturnValue([undefined]);
+        mockUseSearchSections.mockClear();
+        mockUseSearchSections.mockReturnValue({allReports: [], isSearchLoading: false, lastSearchQuery: undefined});
+    });
+
+    describe('fast path', () => {
+        it('does not call useSearchSections when context has IDs and search is not loading', () => {
+            mockSortedReportIDs = ['1', '2', '3'];
+            mockUseOnyx.mockReturnValue([undefined]);
+
+            // Simulate what the wrapper does: reads context + filter
+            const {result} = renderHook(() => {
+                const {sortedReportIDs} = useSearchStateContext();
+                const allReports = useFilterPendingDeleteReports(sortedReportIDs);
+                return {sortedReportIDs, allReports};
+            });
+
+            expect(result.current.allReports).toEqual(['1', '2', '3']);
+            expect(mockUseSearchSections).not.toHaveBeenCalled();
+        });
+    });
+
+    describe('path selection', () => {
+        it('uses fast path when context has IDs and not loading', () => {
+            mockSortedReportIDs = ['1', '2'];
+            // isSearchLoading = false (useOnyx returns undefined for snapshot)
+            mockUseOnyx.mockReturnValue([undefined]);
+
+            const {result} = renderHook(() => {
+                const {sortedReportIDs} = useSearchStateContext();
+                const allReports = useFilterPendingDeleteReports(sortedReportIDs);
+                const isSearchLoading = false;
+                return allReports.length > 0 && !isSearchLoading ? 'fast' : 'full';
+            });
+
+            expect(result.current).toBe('fast');
+            expect(mockUseSearchSections).not.toHaveBeenCalled();
+        });
+
+        it('uses full path when context is empty', () => {
+            mockSortedReportIDs = CONST.EMPTY_ARRAY;
+
+            const {result} = renderHook(() => {
+                const {sortedReportIDs} = useSearchStateContext();
+                const allReports = useFilterPendingDeleteReports(sortedReportIDs);
+                return allReports.length > 0 ? 'fast' : 'full';
+            });
+
+            expect(result.current).toBe('full');
+        });
+
+        it('uses full path when search is loading (pagination)', () => {
+            mockSortedReportIDs = ['1', '2'];
+            const isSearchLoading = true;
+
+            const {result} = renderHook(() => {
+                const {sortedReportIDs} = useSearchStateContext();
+                const allReports = useFilterPendingDeleteReports(sortedReportIDs);
+                return allReports.length > 0 && !isSearchLoading ? 'fast' : 'full';
+            });
+
+            expect(result.current).toBe('full');
+        });
+    });
+});
diff --git a/tests/unit/hooks/useFilterPendingDeleteReports.test.ts b/tests/unit/hooks/useFilterPendingDeleteReports.test.ts
new file mode 100644
index 000000000000..4b9e78a49528
--- /dev/null
+++ b/tests/unit/hooks/useFilterPendingDeleteReports.test.ts
@@ -0,0 +1,104 @@
+import {renderHook} from '@testing-library/react-native';
+import type {OnyxCollection} from 'react-native-onyx';
+import useFilterPendingDeleteReports, {selectPendingDeleteReportKeys} from '@hooks/useFilterPendingDeleteReports';
+import CONST from '@src/CONST';
+import ONYXKEYS from '@src/ONYXKEYS';
+import type {Report} from '@src/types/onyx';
+
+const onyxData: Record<string, unknown> = {};
+
+const mockUseOnyx = jest.fn((key: string, options?: {selector?: (value: unknown) => unknown}) => {
+    const value = onyxData[key];
+    const selectedValue = options?.selector ? options.selector(value as never) : value;
+    return [selectedValue];
+});
+
+jest.mock('@hooks/useOnyx', () => ({
+    __esModule: true,
+    default: (key: string, options?: {selector?: (value: unknown) => unknown}) => mockUseOnyx(key, options),
+}));
+
+describe('useFilterPendingDeleteReports', () => {
+    beforeEach(() => {
+        for (const key of Object.keys(onyxData)) {
+            delete onyxData[key];
+        }
+        mockUseOnyx.mockClear();
+    });
+
+    describe('selectPendingDeleteReportKeys', () => {
+        it('returns empty array for null/undefined collection', () => {
+            expect(selectPendingDeleteReportKeys(null as unknown as OnyxCollection<Report>)).toEqual([]);
+            expect(selectPendingDeleteReportKeys(undefined as unknown as OnyxCollection<Report>)).toEqual([]);
+        });
+
+        it('returns empty array when no reports are pending delete', () => {
+            const reports: OnyxCollection<Report> = {
+                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1'} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
+            };
+            expect(selectPendingDeleteReportKeys(reports)).toEqual([]);
+        });
+
+        it('returns keys of reports with pendingAction DELETE', () => {
+            const reports: OnyxCollection<Report> = {
+                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
+            };
+            expect(selectPendingDeleteReportKeys(reports)).toEqual([`${ONYXKEYS.COLLECTION.REPORT}1`]);
+        });
+
+        it('returns keys of reports with pendingFields.preview DELETE', () => {
+            const reports: OnyxCollection<Report> = {
+                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1'} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2', pendingFields: {preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}} as Report,
+            };
+            expect(selectPendingDeleteReportKeys(reports)).toEqual([`${ONYXKEYS.COLLECTION.REPORT}2`]);
+        });
+
+        it('returns sorted keys when multiple reports are pending delete', () => {
+            const reports: OnyxCollection<Report> = {
+                [`${ONYXKEYS.COLLECTION.REPORT}3`]: {reportID: '3', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1', pendingFields: {preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
+            };
+            expect(selectPendingDeleteReportKeys(reports)).toEqual([`${ONYXKEYS.COLLECTION.REPORT}1`, `${ONYXKEYS.COLLECTION.REPORT}3`]);
+        });
+    });
+
+    describe('useFilterPendingDeleteReports', () => {
+        it('returns all IDs when no reports are pending delete', () => {
+            const {result} = renderHook(() => useFilterPendingDeleteReports(['1', '2', '3']));
+            expect(result.current).toEqual(['1', '2', '3']);
+        });
+
+        it('filters out IDs of reports with pending delete', () => {
+            onyxData[ONYXKEYS.COLLECTION.REPORT] = {
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
+            };
+
+            const {result} = renderHook(() => useFilterPendingDeleteReports(['1', '2', '3']));
+            expect(result.current).toEqual(['1', '3']);
+        });
+
+        it('filters out undefined entries', () => {
+            const {result} = renderHook(() => useFilterPendingDeleteReports(['1', undefined, '3']));
+            expect(result.current).toEqual(['1', '3']);
+        });
+
+        it('returns empty array when all reports are pending delete', () => {
+            onyxData[ONYXKEYS.COLLECTION.REPORT] = {
+                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
+            };
+
+            const {result} = renderHook(() => useFilterPendingDeleteReports(['1', '2']));
+            expect(result.current).toEqual([]);
+        });
+
+        it('returns empty array for empty input', () => {
+            const {result} = renderHook(() => useFilterPendingDeleteReports([]));
+            expect(result.current).toEqual([]);
+        });
+    });
+});
diff --git a/tests/unit/hooks/useSaveSortedReportIDs.test.ts b/tests/unit/hooks/useSaveSortedReportIDs.test.ts
new file mode 100644
index 000000000000..46f0b72744c1
--- /dev/null
+++ b/tests/unit/hooks/useSaveSortedReportIDs.test.ts
@@ -0,0 +1,42 @@
+import {renderHook} from '@testing-library/react-native';
+import type {TransactionListItemType} from '@components/Search/SearchList/ListItem/types';
+import useSaveSortedReportIDs from '@hooks/useSaveSortedReportIDs';
+import CONST from '@src/CONST';
+
+const mockSetSortedReportIDs = jest.fn();
+
+jest.mock('@components/Search/SearchContext', () => ({
+    useSearchActionsContext: () => ({setSortedReportIDs: mockSetSortedReportIDs}),
+}));
+
+describe('useSaveSortedReportIDs', () => {
+    beforeEach(() => {
+        mockSetSortedReportIDs.mockClear();
+    });
+
+    describe('saving report IDs to context', () => {
+        it('stores empty array in context when sorted list is empty', () => {
+            renderHook(() => useSaveSortedReportIDs(CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, []));
+
+            expect(mockSetSortedReportIDs).toHaveBeenCalledWith([]);
+        });
+
+        it('stores only the provided report IDs in context', () => {
+            renderHook(() => useSaveSortedReportIDs(CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, [{reportID: '1'}, {reportID: '3'}] as TransactionListItemType[]));
+
+            expect(mockSetSortedReportIDs).toHaveBeenCalledWith(['1', '3']);
+        });
+
+        it('stores all IDs in context', () => {
+            renderHook(() => useSaveSortedReportIDs(CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, [{reportID: '1'}, {reportID: '2'}, {reportID: '3'}] as TransactionListItemType[]));
+
+            expect(mockSetSortedReportIDs).toHaveBeenCalledWith(['1', '2', '3']);
+        });
+
+        it('clears context when type is not expense-report', () => {
+            renderHook(() => useSaveSortedReportIDs(CONST.SEARCH.DATA_TYPES.EXPENSE, [{reportID: '1'}, {reportID: '2'}] as TransactionListItemType[]));
+
+            expect(mockSetSortedReportIDs).toHaveBeenCalledWith([]);
+        });
+    });
+});
diff --git a/tests/unit/hooks/useSearchSections.test.ts b/tests/unit/hooks/useSearchSections.test.ts
index f0a1ce8831a4..0b669b05e9ee 100644
--- a/tests/unit/hooks/useSearchSections.test.ts
+++ b/tests/unit/hooks/useSearchSections.test.ts
@@ -1,35 +1,21 @@
 import {renderHook} from '@testing-library/react-native';
-import type {OnyxCollection} from 'react-native-onyx';
-import useSearchSections, {selectPendingDeleteReportKeys} from '@hooks/useSearchSections';
+import useSearchSections from '@hooks/useSearchSections';
 import CONST from '@src/CONST';
 import ONYXKEYS from '@src/ONYXKEYS';
-import type {Report} from '@src/types/onyx';
 
 const onyxData: Record<string, unknown> = {};
 
-const mockUseOnyx = jest.fn(
-    (
-        key: string,
-        options?: {
-            selector?: (value: unknown) => unknown;
-        },
-    ) => {
-        const value = onyxData[key];
-        const selectedValue = options?.selector ? options.selector(value as never) : value;
-        return [selectedValue];
-    },
-);
+const mockUseOnyx = jest.fn((key: string, options?: {selector?: (value: unknown) => unknown}) => {
+    const value = onyxData[key];
+    const selectedValue = options?.selector ? options.selector(value as never) : value;
+    return [selectedValue];
+});
 
 jest.mock('@hooks/useOnyx', () => ({
     __esModule: true,
     default: (key: string, options?: {selector?: (value: unknown) => unknown}) => mockUseOnyx(key, options),
 }));
 
-jest.mock('@hooks/useCurrentUserPersonalDetails', () => ({
-    __esModule: true,
-    default: () => ({accountID: 1, email: 'test@test.com'}),
-}));
-
 jest.mock('@hooks/useLocalize', () => ({
     __esModule: true,
     default: () => ({
@@ -39,6 +25,11 @@ jest.mock('@hooks/useLocalize', () => ({
     }),
 }));
 
+jest.mock('@hooks/useCurrentUserPersonalDetails', () => ({
+    __esModule: true,
+    default: () => ({accountID: 1, email: 'test@test.com'}),
+}));
+
 jest.mock('@hooks/useActionLoadingReportIDs', () => ({
     __esModule: true,
     default: () => new Set(),
@@ -49,12 +40,13 @@ jest.mock('@hooks/useArchivedReportsIdSet', () => ({
     default: () => new Set(),
 }));
 
-// Mock getSections/getSortedSections to return controlled report IDs
 const mockGetSortedSections = jest.fn();
+const mockGetSections = jest.fn();
 jest.mock('@libs/SearchUIUtils', () => ({
-    getSections: () => [[], {}],
     // eslint-disable-next-line @typescript-eslint/no-unsafe-return
     getSortedSections: (...args: unknown[]) => mockGetSortedSections(...args),
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+    getSections: (...args: unknown[]) => mockGetSections(...args),
 }));
 
 describe('useSearchSections', () => {
@@ -65,119 +57,57 @@ describe('useSearchSections', () => {
         mockUseOnyx.mockClear();
         mockGetSortedSections.mockReset();
         mockGetSortedSections.mockReturnValue([]);
+        mockGetSections.mockReset();
+        mockGetSections.mockReturnValue([[]]);
     });
 
-    describe('selectPendingDeleteReportKeys', () => {
-        it('returns empty array for null/undefined collection', () => {
-            expect(selectPendingDeleteReportKeys(null as unknown as OnyxCollection<Report>)).toEqual([]);
-            expect(selectPendingDeleteReportKeys(undefined as unknown as OnyxCollection<Report>)).toEqual([]);
-        });
-
-        it('returns empty array when no reports are pending delete', () => {
-            const reports: OnyxCollection<Report> = {
-                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1'} as Report,
-                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
+    describe('report ID computation', () => {
+        it('calls getSortedSections and returns results', () => {
+            mockGetSortedSections.mockReturnValue([{reportID: '1'}, {reportID: '2'}]);
+            mockGetSections.mockReturnValue([[{reportID: '1'}, {reportID: '2'}]]);
+            onyxData[ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY] = {
+                queryJSON: {hash: '123', type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, status: CONST.SEARCH.STATUS.EXPENSE.ALL},
             };
-            expect(selectPendingDeleteReportKeys(reports)).toEqual([]);
-        });
-
-        it('returns keys of reports with pendingAction DELETE', () => {
-            const reports: OnyxCollection<Report> = {
-                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
-                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
+            onyxData[`${ONYXKEYS.COLLECTION.SNAPSHOT}123`] = {
+                data: {reports: {}},
+                search: {isLoading: false},
             };
-            expect(selectPendingDeleteReportKeys(reports)).toEqual([`${ONYXKEYS.COLLECTION.REPORT}1`]);
-        });
 
-        it('returns keys of reports with pendingFields.preview DELETE', () => {
-            const reports: OnyxCollection<Report> = {
-                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1'} as Report,
-                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2', pendingFields: {preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}} as Report,
-            };
-            expect(selectPendingDeleteReportKeys(reports)).toEqual([`${ONYXKEYS.COLLECTION.REPORT}2`]);
-        });
-
-        it('returns sorted keys when multiple reports are pending delete', () => {
-            const reports: OnyxCollection<Report> = {
-                [`${ONYXKEYS.COLLECTION.REPORT}3`]: {reportID: '3', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as Report,
-                [`${ONYXKEYS.COLLECTION.REPORT}1`]: {reportID: '1', pendingFields: {preview: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}} as Report,
-                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2'} as Report,
-            };
-            const result = selectPendingDeleteReportKeys(reports);
-            expect(result).toEqual([`${ONYXKEYS.COLLECTION.REPORT}1`, `${ONYXKEYS.COLLECTION.REPORT}3`]);
-        });
-    });
-
-    describe('pending delete filtering', () => {
-        it('returns empty allReports when no search query exists', () => {
             const {result} = renderHook(() => useSearchSections());
 
-            expect(result.current.allReports).toEqual([]);
+            expect(mockGetSortedSections).toHaveBeenCalled();
+            expect(result.current.allReports).toEqual(['1', '2']);
         });
 
-        it('filters out pending delete reports from allReports', () => {
-            const pendingDeleteKeys = [`${ONYXKEYS.COLLECTION.REPORT}2`];
-            const snapshotHash = 12345;
-
+        it('filters out pending delete reports from results', () => {
             mockGetSortedSections.mockReturnValue([{reportID: '1'}, {reportID: '2'}, {reportID: '3'}]);
-
-            mockUseOnyx.mockImplementation(
-                (
-                    key: string,
-                    options?: {
-                        selector?: (value: unknown) => unknown;
-                    },
-                ) => {
-                    if (key === ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY) {
-                        return [{queryJSON: {type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, hash: snapshotHash}}];
-                    }
-                    if (key === `${ONYXKEYS.COLLECTION.SNAPSHOT}${snapshotHash}`) {
-                        return [{data: {}, search: {isLoading: false}}];
-                    }
-                    if (key === ONYXKEYS.COLLECTION.REPORT) {
-                        return [pendingDeleteKeys];
-                    }
-                    const value = onyxData[key];
-                    const selectedValue = options?.selector ? options.selector(value as never) : value;
-                    return [selectedValue];
-                },
-            );
+            mockGetSections.mockReturnValue([[{reportID: '1'}, {reportID: '2'}, {reportID: '3'}]]);
+            onyxData[ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY] = {
+                queryJSON: {hash: '123', type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, status: CONST.SEARCH.STATUS.EXPENSE.ALL},
+            };
+            onyxData[`${ONYXKEYS.COLLECTION.SNAPSHOT}123`] = {
+                data: {reports: {}},
+                search: {isLoading: false},
+            };
+            onyxData[ONYXKEYS.COLLECTION.REPORT] = {
+                [`${ONYXKEYS.COLLECTION.REPORT}2`]: {reportID: '2', pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE} as unknown as Report,
+            };
 
             const {result} = renderHook(() => useSearchSections());
 
             expect(result.current.allReports).toEqual(['1', '3']);
         });
 
-        it('returns all reports when none are pending delete', () => {
-            const snapshotHash = 12345;
-
-            mockGetSortedSections.mockReturnValue([{reportID: '1'}, {reportID: '2'}, {reportID: '3'}]);
-
-            mockUseOnyx.mockImplementation(
-                (
-                    key: string,
-                    options?: {
-                        selector?: (value: unknown) => unknown;
-                    },
-                ) => {
-                    if (key === ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY) {
-                        return [{queryJSON: {type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, hash: snapshotHash}}];
-                    }
-                    if (key === `${ONYXKEYS.COLLECTION.SNAPSHOT}${snapshotHash}`) {
-                        return [{data: {}, search: {isLoading: false}}];
-                    }
-                    if (key === ONYXKEYS.COLLECTION.REPORT) {
-                        return [[]];
-                    }
-                    const value = onyxData[key];
-                    const selectedValue = options?.selector ? options.selector(value as never) : value;
-                    return [selectedValue];
-                },
-            );
+        it('returns empty allReports when search results are not yet loaded', () => {
+            onyxData[ONYXKEYS.REPORT_NAVIGATION_LAST_SEARCH_QUERY] = {
+                queryJSON: {hash: '123', type: CONST.SEARCH.DATA_TYPES.EXPENSE_REPORT, status: CONST.SEARCH.STATUS.EXPENSE.ALL},
+            };
+            // No snapshot data — simulates deep-link before search has run
 
             const {result} = renderHook(() => useSearchSections());
 
-            expect(result.current.allReports).toEqual(['1', '2', '3']);
+            expect(mockGetSortedSections).not.toHaveBeenCalled();
+            expect(result.current.allReports).toEqual([]);
         });
     });
 });
