From e7faed05fe57534e8345c4c3fabbbcfacfea6f27 Mon Sep 17 00:00:00 2001 From: Huu Le <20178761+huult@users.noreply.github.com> Date: Wed, 6 Aug 2025 12:49:19 +0700 Subject: [PATCH 1/2] reset default query on error or clear cache --- src/components/Search/SearchContext.tsx | 11 +++++++++++ src/components/Search/index.tsx | 19 ++++++++++++++++++- src/components/Search/types.ts | 2 ++ .../Troubleshoot/TroubleshootPage.tsx | 4 +++- 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/components/Search/SearchContext.tsx b/src/components/Search/SearchContext.tsx index 5ecb1f8db75f..d768dbe56510 100644 --- a/src/components/Search/SearchContext.tsx +++ b/src/components/Search/SearchContext.tsx @@ -15,6 +15,7 @@ const defaultSearchContextData: SearchContextData = { selectedReports: [], isOnSearch: false, shouldTurnOffSelectionMode: false, + shouldResetSearchQuery: false, }; const defaultSearchContext: SearchContext = { @@ -31,6 +32,7 @@ const defaultSearchContext: SearchContext = { setShouldShowFiltersBarLoading: () => {}, shouldShowSelectAllMatchingItems: () => {}, selectAllMatchingItems: () => {}, + setShouldResetSearchQuery: () => {}, }; const Context = React.createContext(defaultSearchContext); @@ -173,6 +175,13 @@ function SearchContextProvider({children}: ChildrenProps) { [searchContextData.selectedTransactionIDs, searchContextData.selectedTransactions], ); + const setShouldResetSearchQuery = useCallback((shouldReset: boolean) => { + setSearchContextData((prevState) => ({ + ...prevState, + shouldResetSearchQuery: shouldReset, + })); + }, []); + const searchContext = useMemo( () => ({ ...searchContextData, @@ -188,6 +197,7 @@ function SearchContextProvider({children}: ChildrenProps) { shouldShowSelectAllMatchingItems, areAllMatchingItemsSelected, selectAllMatchingItems, + setShouldResetSearchQuery, }), [ searchContextData, @@ -200,6 +210,7 @@ function SearchContextProvider({children}: ChildrenProps) { shouldShowSelectAllMatchingItems, showSelectAllMatchingItems, areAllMatchingItemsSelected, + setShouldResetSearchQuery, ], ); diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 1742cf8b14ca..db2342e3c5ee 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -27,7 +27,7 @@ import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNa import Performance from '@libs/Performance'; import {getIOUActionForTransactionID, isExportIntegrationAction, isIntegrationMessageAction} from '@libs/ReportActionsUtils'; import {canEditFieldOfMoneyRequest, generateReportID, isArchivedReport} from '@libs/ReportUtils'; -import {buildSearchQueryString} from '@libs/SearchQueryUtils'; +import {buildCannedSearchQuery, buildSearchQueryString} from '@libs/SearchQueryUtils'; import { getColumnsToShow, getListItem, @@ -165,6 +165,8 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS shouldShowSelectAllMatchingItems, areAllMatchingItemsSelected, selectAllMatchingItems, + shouldResetSearchQuery, + setShouldResetSearchQuery, } = useSearchContext(); const [offset, setOffset] = useState(0); @@ -646,6 +648,21 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS const hasErrors = Object.keys(searchResults?.errors ?? {}).length > 0 && !isOffline; + useEffect(() => { + const currentRoute = Navigation.getActiveRouteWithoutParams(); + + if ((hasErrors || shouldResetSearchQuery) && currentRoute === '/') { + // Use requestAnimationFrame to safely update navigation params without overriding the current route + requestAnimationFrame(() => { + Navigation.setParams({q: buildCannedSearchQuery()}); + + if (shouldResetSearchQuery) { + setShouldResetSearchQuery(false); + } + }); + } + }, [hasErrors, queryJSON, searchResults, shouldResetSearchQuery, setShouldResetSearchQuery]); + const fetchMoreResults = useCallback(() => { if (!isFocused || !searchResults?.search?.hasMoreResults || shouldShowLoadingState || shouldShowLoadingMoreItems) { return; diff --git a/src/components/Search/types.ts b/src/components/Search/types.ts index 717c923f75f1..056ceb4b3047 100644 --- a/src/components/Search/types.ts +++ b/src/components/Search/types.ts @@ -76,6 +76,7 @@ type SearchContextData = { selectedReports: SelectedReports[]; isOnSearch: boolean; shouldTurnOffSelectionMode: boolean; + shouldResetSearchQuery: boolean; }; type SearchContext = SearchContextData & { @@ -99,6 +100,7 @@ type SearchContext = SearchContextData & { shouldShowSelectAllMatchingItems: (shouldShow: boolean) => void; areAllMatchingItemsSelected: boolean; selectAllMatchingItems: (on: boolean) => void; + setShouldResetSearchQuery: (shouldReset: boolean) => void; }; type ASTNode = { diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx index db4e2d80c293..d07fc3d6954b 100644 --- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx +++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx @@ -14,6 +14,7 @@ import RecordTroubleshootDataToolMenu from '@components/RecordTroubleshootDataTo import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; +import {useSearchContext} from '@components/Search/SearchContext'; import Section from '@components/Section'; import Switch from '@components/Switch'; import TestToolMenu from '@components/TestToolMenu'; @@ -51,7 +52,7 @@ function TroubleshootPage() { const [shouldStoreLogs] = useOnyx(ONYXKEYS.SHOULD_STORE_LOGS, {canBeMissing: true}); const [shouldMaskOnyxState = true] = useOnyx(ONYXKEYS.SHOULD_MASK_ONYX_STATE, {canBeMissing: true}); const {resetOptions} = useOptionsList({shouldInitialize: false}); - + const {setShouldResetSearchQuery} = useSearchContext(); const exportOnyxState = useCallback(() => { ExportOnyxState.readFromOnyxDatabase().then((value: Record) => { const dataToShare = ExportOnyxState.maskOnyxState(value, shouldMaskOnyxState); @@ -152,6 +153,7 @@ function TroubleshootPage() { onConfirm={() => { setIsConfirmationModalVisible(false); resetOptions(); + setShouldResetSearchQuery(true); clearOnyxAndResetApp(); }} onCancel={() => setIsConfirmationModalVisible(false)} From c74dad218bf59efa072fb18e51e8f47bb3284374 Mon Sep 17 00:00:00 2001 From: Huu Le <20178761+huult@users.noreply.github.com> Date: Wed, 6 Aug 2025 14:16:07 +0700 Subject: [PATCH 2/2] reset shouldResetSearchQuery flag when creating a new search --- src/components/Search/SearchRouter/SearchRouter.tsx | 7 ++++++- src/components/Search/index.tsx | 10 ++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/Search/SearchRouter/SearchRouter.tsx b/src/components/Search/SearchRouter/SearchRouter.tsx index affdeb1a5431..0f4d7d6a3b22 100644 --- a/src/components/Search/SearchRouter/SearchRouter.tsx +++ b/src/components/Search/SearchRouter/SearchRouter.tsx @@ -10,6 +10,7 @@ import {usePersonalDetails} from '@components/OnyxListItemProvider'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; import type {GetAdditionalSectionsCallback} from '@components/Search/SearchAutocompleteList'; import SearchAutocompleteList from '@components/Search/SearchAutocompleteList'; +import {useSearchContext} from '@components/Search/SearchContext'; import SearchInputSelectionWrapper from '@components/Search/SearchInputSelectionWrapper'; import type {SearchQueryString} from '@components/Search/types'; import type {SearchQueryItem} from '@components/SelectionList/Search/SearchQueryListItem'; @@ -82,6 +83,7 @@ type SearchRouterProps = { function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDisplayed}: SearchRouterProps, ref: React.Ref) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const {setShouldResetSearchQuery} = useSearchContext(); const [, recentSearchesMetadata] = useOnyx(ONYXKEYS.RECENT_SEARCHES, {canBeMissing: true}); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const personalDetails = usePersonalDetails(); @@ -259,6 +261,9 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla return; } + // Reset the search query flag when performing a new search + setShouldResetSearchQuery(false); + backHistory(() => { onRouterClose(); Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query: updatedQuery})); @@ -267,7 +272,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla setTextInputValue(''); setAutocompleteQueryValue(''); }, - [autocompleteSubstitutions, onRouterClose, setTextInputValue], + [autocompleteSubstitutions, onRouterClose, setTextInputValue, setShouldResetSearchQuery], ); const setTextAndUpdateSelection = useCallback( diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index db2342e3c5ee..d53140b9df90 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -650,16 +650,14 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS useEffect(() => { const currentRoute = Navigation.getActiveRouteWithoutParams(); - - if ((hasErrors || shouldResetSearchQuery) && currentRoute === '/') { + if (hasErrors && (currentRoute === '/' || (shouldResetSearchQuery && currentRoute === '/search'))) { // Use requestAnimationFrame to safely update navigation params without overriding the current route requestAnimationFrame(() => { Navigation.setParams({q: buildCannedSearchQuery()}); - - if (shouldResetSearchQuery) { - setShouldResetSearchQuery(false); - } }); + if (shouldResetSearchQuery) { + setShouldResetSearchQuery(false); + } } }, [hasErrors, queryJSON, searchResults, shouldResetSearchQuery, setShouldResetSearchQuery]);