Skip to content

Commit de8a578

Browse files
authored
Merge pull request Expensify#65575 from callstack-internal/perf/limit-search-routes-to-render
Perf: Limit previous Search screens mounted
2 parents feb220c + 2c04548 commit de8a578

4 files changed

Lines changed: 30 additions & 19 deletions

File tree

contributingGuides/NAVIGATION.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -654,7 +654,7 @@ function useCustomRootStackNavigatorState({state}: CustomStateHookProps) {
654654
}
655655
```
656656

657-
To optimize the number of routes rendered in `RootStackNavigator` we limit the number of `FullScreenNavigators` rendered to 2 (we need to render the previous fullscreen too for the transition animations to work well).
657+
To optimize the number of routes rendered in `RootStackNavigator` we limit the number of `FullScreenNavigators` rendered to 2 (we need to render the previous fullscreen too for the transition animations to work well). There's an exception for `SearchFullscreenNavigator` where we render only last route when possible due to performance implications. The idea stays the same.
658658

659659
- `src/libs/Navigation/AppNavigator/createSearchFullscreenNavigator/index.tsx`
660660

@@ -664,10 +664,9 @@ function useCustomEffects(props: CustomEffectsHookProps) {
664664
usePreserveNavigatorState(props.state, props.parentRoute);
665665
}
666666
667-
// This is a custom state hook that is used to render the last two routes in the stack.
668-
// We do this to improve the performance of the search results screen.
669-
function useCustomState({state}: CustomStateHookProps) {
670-
const routesToRender = [...state.routes.slice(-2)];
667+
// For web we only render last route in SearchFullscreenNavigator. Other navigators are keep last two routes mounted. The idea stays the same.
668+
export default function useCustomState({state}: CustomStateHookProps) {
669+
const routesToRender = state.routes.slice(-1);
671670
return {...state, routes: routesToRender, index: routesToRender.length - 1};
672671
}
673672
```

src/libs/Navigation/AppNavigator/createSearchFullscreenNavigator/index.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,15 @@ import usePreserveNavigatorState from '@libs/Navigation/AppNavigator/createSplit
55
import useNavigationResetOnLayoutChange from '@libs/Navigation/AppNavigator/useNavigationResetOnLayoutChange';
66
import createPlatformStackNavigatorComponent from '@navigation/PlatformStackNavigation/createPlatformStackNavigatorComponent';
77
import defaultPlatformStackScreenOptions from '@navigation/PlatformStackNavigation/defaultPlatformStackScreenOptions';
8-
import type {
9-
CustomEffectsHookProps,
10-
CustomStateHookProps,
11-
PlatformStackNavigationEventMap,
12-
PlatformStackNavigationOptions,
13-
PlatformStackNavigationState,
14-
} from '@navigation/PlatformStackNavigation/types';
8+
import type {CustomEffectsHookProps, PlatformStackNavigationEventMap, PlatformStackNavigationOptions, PlatformStackNavigationState} from '@navigation/PlatformStackNavigation/types';
159
import SearchFullscreenRouter from './SearchFullscreenRouter';
10+
import useCustomState from './useCustomState';
1611

1712
function useCustomEffects(props: CustomEffectsHookProps) {
1813
useNavigationResetOnLayoutChange(props);
1914
usePreserveNavigatorState(props.state, props.parentRoute);
2015
}
2116

22-
// This is a custom state hook that is used to render the last two routes in the stack.
23-
// We do this to improve the performance of the search results screen.
24-
function useCustomState({state}: CustomStateHookProps) {
25-
const routesToRender = [...state.routes.slice(-2)];
26-
return {...state, routes: routesToRender, index: routesToRender.length - 1};
27-
}
28-
2917
const SearchFullscreenNavigatorComponent = createPlatformStackNavigatorComponent('SearchFullscreenNavigator', {
3018
createRouter: SearchFullscreenRouter,
3119
defaultScreenOptions: defaultPlatformStackScreenOptions,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
2+
import SCREENS from '@src/SCREENS';
3+
4+
/**
5+
* This is a custom state hook for SearchFullscreenNavigator that is used to render the last two search routes in the stack.
6+
* For native platforms, we render the last two routes to allow users to return by swiping left.
7+
* @see SearchFullscreenNavigator use only!
8+
*/
9+
export default function useCustomState({state}: CustomStateHookProps) {
10+
const lastSearchNavigatorIndex = state.routes.findLastIndex((route) => route.name === SCREENS.SEARCH.ROOT);
11+
const routesToRender = state.routes.slice(Math.max(0, lastSearchNavigatorIndex), state.routes.length);
12+
return {...state, routes: routesToRender, index: routesToRender.length - 1};
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type {CustomStateHookProps} from '@libs/Navigation/PlatformStackNavigation/types';
2+
3+
/**
4+
* This is a custom state hook for SearchFullscreenNavigator that is used to render the last search route in the stack.
5+
* We do this to improve the performance of the search results screen by avoiding unnecessary re-renders of underneath routes.
6+
* @see SearchFullscreenNavigator use only!
7+
*/
8+
export default function useCustomState({state}: CustomStateHookProps) {
9+
const routesToRender = state.routes.slice(-1);
10+
return {...state, routes: routesToRender, index: routesToRender.length - 1};
11+
}

0 commit comments

Comments
 (0)