@@ -6,6 +6,13 @@ import type {NavigationRoute, SplitNavigatorName} from '@libs/Navigation/types';
66import NAVIGATORS from '@src/NAVIGATORS' ;
77import ensureTabNavigatorRoutes from './ensureTabNavigatorRoutes' ;
88
9+ // TODO: deploy-blocker hotfix for #89006 — slicing tab state breaks rehydration on iOS swipe-back.
10+ // Skipping the slice until we exceed the threshold preserves the underlying TAB_NAVIGATOR's nested
11+ // state so the gesture restores it correctly. This is a temporary fix; the proper solution is to
12+ // rebuild the TAB_NAVIGATOR state from `preservedNavigatorStates` on rehydration so the magic
13+ // number can go away. We'll address this shortly — tracked in https://github.com/Expensify/App/issues/89179.
14+ const SKIP_SLICE_TAB_THRESHOLD = 4 ;
15+
916// Swiping back on iOS does not work properly when the preloaded route has gestureEnabled set to false.
1017// Therefore, on screens where swiping should work, preloadedRoutes will be an empty array during rendering to ensure swiping works properly.
1118// Once this bug is fixed, this file should be deleted and index.android.ts renamed to index.native.ts.
@@ -35,12 +42,19 @@ function getShouldHidePreloadedRoutes(route?: NavigationRoute) {
3542// This is an optimization to keep mounted only last few screens in the stack.
3643// On native platforms, we store the last two routes to handle swiping back.
3744export default function useCustomRootStackNavigatorState ( { state} : CustomStateHookProps ) {
38- const lastSplitIndex = state . routes . findLastIndex ( ( route ) => isFullScreenName ( route . name ) ) ;
39- const indexToSlice = Math . max ( 0 , lastSplitIndex - 1 ) ;
40- const slicedRoutes = state . routes . slice ( indexToSlice , state . routes . length ) ;
41- const routesToRender = ensureTabNavigatorRoutes ( slicedRoutes , indexToSlice , state . routes ) ;
45+ const tabCount = state . routes . reduce ( ( acc , route ) => ( route . name === NAVIGATORS . TAB_NAVIGATOR ? acc + 1 : acc ) , 0 ) ;
46+
47+ let stateToRender : typeof state ;
48+ if ( tabCount <= SKIP_SLICE_TAB_THRESHOLD ) {
49+ stateToRender = state ;
50+ } else {
51+ const lastSplitIndex = state . routes . findLastIndex ( ( route ) => isFullScreenName ( route . name ) ) ;
52+ const indexToSlice = Math . max ( 0 , lastSplitIndex - 1 ) ;
53+ const slicedRoutes = state . routes . slice ( indexToSlice , state . routes . length ) ;
54+ const routesToRender = ensureTabNavigatorRoutes ( slicedRoutes , indexToSlice , state . routes ) ;
55+ stateToRender = { ...state , routes : routesToRender , index : routesToRender . length - 1 } ;
56+ }
4257
43- const stateToRender = { ...state , routes : routesToRender , index : routesToRender . length - 1 } ;
4458 if ( getShouldHidePreloadedRoutes ( stateToRender . routes . at ( - 1 ) ) ) {
4559 return { ...stateToRender , preloadedRoutes : [ ] } ;
4660 }
0 commit comments