@@ -2,7 +2,7 @@ import type {MaterialTopTabNavigationEventMap} from '@react-navigation/material-
22import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs' ;
33import type { EventMapCore , NavigationState , ParamListBase , ScreenListeners } from '@react-navigation/native' ;
44import { useRoute } from '@react-navigation/native' ;
5- import React , { useCallback , useContext , useEffect , useRef , useState } from 'react' ;
5+ import React , { useCallback , useContext , useEffect , useMemo , useRef , useState } from 'react' ;
66import { useOnyx } from 'react-native-onyx' ;
77import FocusTrapContainerElement from '@components/FocusTrap/FocusTrapContainerElement' ;
88import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator' ;
@@ -69,6 +69,24 @@ const TopTab = createMaterialTopTabNavigator<ParamListBase, string>();
6969// This provider is placed in the OnyxTabNavigator component and the consumer is in the TabScreenWithFocusTrapWrapper component.
7070const TabFocusTrapContext = React . createContext < ( tabName : string , containerElement : HTMLElement | null ) => void > ( ( ) => { } ) ;
7171
72+ const getTabNames = ( children : React . ReactNode ) : string [ ] => {
73+ const result : string [ ] = [ ] ;
74+
75+ React . Children . forEach ( children , ( child ) => {
76+ if ( ! React . isValidElement ( child ) ) {
77+ return ;
78+ }
79+
80+ const element = child as React . ReactElement < { name ?: string } > ;
81+
82+ if ( typeof element . props . name === 'string' ) {
83+ result . push ( element . props . name ) ;
84+ }
85+ } ) ;
86+
87+ return result ;
88+ } ;
89+
7290// This takes all the same props as MaterialTopTabsNavigator: https://reactnavigation.org/docs/material-top-tab-navigator/#props,
7391// except ID is now required, and it gets a `selectedTab` from Onyx
7492// It also takes 2 more optional callbacks to manage the focus trap container elements of the tab bar and the active tab
@@ -94,6 +112,10 @@ function OnyxTabNavigator({
94112 const [ focusTrapContainerElementMapping , setFocusTrapContainerElementMapping ] = useState < Record < string , HTMLElement > > ( { } ) ;
95113 const [ selectedTab , selectedTabResult ] = useOnyx ( `${ ONYXKEYS . COLLECTION . SELECTED_TAB } ${ id } ` , { canBeMissing : false } ) ;
96114
115+ const tabNames = useMemo ( ( ) => getTabNames ( children ) , [ children ] ) ;
116+
117+ const validInitialTab = selectedTab && tabNames . includes ( selectedTab ) ? selectedTab : defaultSelectedTab ;
118+
97119 const LazyPlaceholder = useCallback ( ( ) => {
98120 return < FullScreenLoadingIndicator /> ;
99121 } , [ ] ) ;
@@ -146,7 +168,7 @@ function OnyxTabNavigator({
146168 /* eslint-disable-next-line react/jsx-props-no-spreading */
147169 { ...rest }
148170 id = { id }
149- initialRouteName = { selectedTab ?? defaultSelectedTab }
171+ initialRouteName = { validInitialTab }
150172 backBehavior = "initialRoute"
151173 keyboardDismissMode = "none"
152174 tabBar = { TabBarWithFocusTrapInclusion }
0 commit comments