Skip to content

Commit 5dbc329

Browse files
authored
Merge pull request Expensify#89082 from software-mansion-labs/borys3kk-fix-filter-pills-problems
Fix deploy blockers from filters after introducing Bottom Tab Navigator
2 parents c79b2d0 + 90f9d66 commit 5dbc329

2 files changed

Lines changed: 27 additions & 26 deletions

File tree

src/components/Search/SearchPageHeader/SearchAdvancedFiltersButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ function SearchAdvancedFiltersButton({queryJSON}: SearchAdvancedFiltersButtonPro
2626
const {shouldUseNarrowLayout, isMediumScreenWidth} = useResponsiveLayout();
2727
const expensifyIcons = useMemoizedLazyExpensifyIcons(['Filter']);
2828
const filterFormValues = useFilterFormValues(queryJSON);
29-
useSearchFilterSync(filterFormValues);
29+
useSearchFilterSync(queryJSON, filterFormValues);
3030

3131
const openAdvancedFilters = () => {
3232
updateAdvancedFilters(filterFormValues);

src/hooks/useSearchFilterSync.ts

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
11
import {useIsFocused} from '@react-navigation/native';
2-
import {useEffect, useRef} from 'react';
2+
import {useEffect} from 'react';
3+
import type {SearchQueryJSON} from '@components/Search/types';
34
import {updateAdvancedFilters} from '@libs/actions/Search';
5+
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
46
import type {SearchAdvancedFiltersForm} from '@src/types/form';
57

68
/**
7-
* Syncs computed filter form values to the SEARCH_ADVANCED_FILTERS_FORM Onyx key
8-
* whenever they change. Call from SearchAdvanceFiltersButton which already computes formValues
9-
* via useFilterFormValues.
10-
*
11-
* The isFocused guard prevents the blurred (previous) SearchPage instance—kept
12-
* mounted during navigation transition animations—from overwriting the Onyx form
13-
* state that was already written by the newly focused instance.
14-
*
15-
* On narrow layout (iOS native), navigating to Advanced Filters causes this screen
16-
* to lose focus. When the user returns, the screen regains focus and this effect
17-
* would re-fire. Without the prevIsFocusedRef guard below, it would overwrite any
18-
* form changes made by Advanced Filters (e.g. resetting a date range) with stale
19-
* values derived from the unchanged URL query parameter.
9+
* Module-level: tracks the last URL query signature that was synced into the
10+
* SEARCH_ADVANCED_FILTERS_FORM Onyx key. We deliberately keep this outside the
11+
* hook so it survives unmount/remount of SearchAdvancedFiltersButton. The
12+
* button is gated by SearchActionsBarSwitch (`showStatic` flips during
13+
* `startTransition` after navigation) which causes the hook to remount and
14+
* would otherwise reset a per-component ref to null — causing the sync to
15+
* fire again with form values derived from the *old* URL, clobbering any
16+
* Onyx.merge that was just done by the Advanced Filters flow (e.g. Save Date
17+
* before the URL has been replaced by View Results).
2018
*/
21-
function useSearchFilterSync(formValues: Partial<SearchAdvancedFiltersForm>) {
19+
let lastSyncedQuerySig: string | null = null;
20+
21+
/**
22+
* Syncs computed filter form values to the SEARCH_ADVANCED_FILTERS_FORM Onyx
23+
* key when the URL query string actually changes. The form is the source for
24+
* the filter pills shown in the Search header — overwriting it on every
25+
* re-render (or every fresh mount with the same URL) would erase concurrent
26+
* Onyx.merge writes from Advanced Filters and leave the pill missing.
27+
*/
28+
function useSearchFilterSync(queryJSON: SearchQueryJSON | undefined, formValues: Partial<SearchAdvancedFiltersForm>) {
2229
const isFocused = useIsFocused();
23-
const prevIsFocusedRef = useRef(isFocused);
2430

2531
useEffect(() => {
26-
const wasPreviouslyFocused = prevIsFocusedRef.current;
27-
prevIsFocusedRef.current = isFocused;
28-
2932
if (!isFocused) {
3033
return;
3134
}
32-
33-
// Skip syncing when just regaining focus to avoid overwriting form
34-
// changes made while this screen was unfocused (e.g. Advanced Filters).
35-
if (!wasPreviouslyFocused) {
35+
const querySig = queryJSON ? buildSearchQueryString(queryJSON) : null;
36+
if (lastSyncedQuerySig === querySig) {
3637
return;
3738
}
38-
39+
lastSyncedQuerySig = querySig;
3940
updateAdvancedFilters(formValues, true);
40-
}, [formValues, isFocused]);
41+
}, [queryJSON, formValues, isFocused]);
4142
}
4243

4344
export default useSearchFilterSync;

0 commit comments

Comments
 (0)