I'm using Typescript and since this question is more theoretical, I will only post the necessary code. I have a material top tab navigation looking like this:
TabNavigator.tsx
const Tab = createMaterialTopTabNavigator<GameTabParamList>();
const GameTabs: FC = () => {
return (
<Tab.Navigator
initialRouteName={Screens.HOME_SCREEN}
tabBarPosition="bottom"
screenOptions={{
lazy: true,
tabBarStyle: {display: 'none'},
swipeEnabled: false, // This should be equal to props that are found in the multiple screens
}}
backBehavior='none'>
<Tab.Screen
name={Screens.AVAILABLE_PRIZES_SCREEN}
component={AvailablePrizesScreen}
/>
<Tab.Screen name={Screens.HOME_SCREEN} component={HomeScreen} />
<Tab.Screen
name={Screens.WON_PRIZES_SCREEN}
component={WonPrizesScreen}
/>
</Tab.Navigator>
);
};
HomeScreen.txs
const HomeScreen: FC = () => {
const {
isInitialized,
isLoading,
adShowing,
playGame,
localCount,
isAnimationPlaying,
winAnimationRef,
handleWinAnimationFinished,
isFlashAnimationPlaying,
navToSettingsScreen,
displayPrizeId,
displayPrizeTitle,
displayPrizeDesc,
displayPrizeTier,
displayPrizeType,
isShowingPrize,
handleHidePrize,
handleFlashAnimationFinished,
navigation,
} = useHomeScreen();
...
}
The goal is to make the swipeEnabled equal to the HomeScreen's isloading and isInitialized variables. So it should look like this:
TabNavigator.tsx
screenOptions={{
lazy: true,
tabBarStyle: {display: 'none'},
swipeEnabled: !isLoading || !isInitialized, // <-- how do I get this here?
}}
The problem is, how do I get the isLoading and isInitialized variables from the HomeScreen component to the GameTabs component?
Create another state inside GameTabs component and pass it's setState function to each screen component to keep track of isLoading and isInitialized variables.
TabNavigator.tsx
const Tab = createMaterialTopTabNavigator<GameTabParamList>();
const GameTabs: FC = () => {
const [swipeEnabled, setSwipeEnabled] = useState(false);
return (
<Tab.Navigator
initialRouteName={Screens.HOME_SCREEN}
tabBarPosition="bottom"
screenOptions={{
lazy: true,
tabBarStyle: {display: 'none'},
swipeEnabled: swipeEnabled,
}}
backBehavior='none'>
<Tab.Screen
name={Screens.AVAILABLE_PRIZES_SCREEN}
component={AvailablePrizesScreen}
/>
<Tab.Screen name={Screens.HOME_SCREEN} render={() => <HomeScreen setSwipeEnabled={setSwipeEnabled}/>} />
<Tab.Screen
name={Screens.WON_PRIZES_SCREEN}
component={WonPrizesScreen}
/>
</Tab.Navigator>
);
};
HomeScreen.txs
Inside HomeScreen, use useEffect to set swipeEnabled state having isLoading and isInitialized variables inside the dependency array of the useEffect.
const HomeScreen: FC = ({ setSwipeEnabled }) => {
const {
isInitialized,
isLoading,
adShowing,
playGame,
localCount,
isAnimationPlaying,
winAnimationRef,
handleWinAnimationFinished,
isFlashAnimationPlaying,
navToSettingsScreen,
displayPrizeId,
displayPrizeTitle,
displayPrizeDesc,
displayPrizeTier,
displayPrizeType,
isShowingPrize,
handleHidePrize,
handleFlashAnimationFinished,
navigation,
} = useHomeScreen();
useEffect(() => {
setSwipeEnabled(!isLoading || !isInitialized);
}, [isLoading, isInitialized]);
...
}
This is one solution that works, but @Kavindu Vindika offered a solution that may be cleaner.
I found the soloution. Turns out, the navigation prop that get's passed to each screen has a setOptions method. So you can simply call that when each screen gets mounted. For example, after I fetch the navigation prop I simply did:
navigation.setOptions({swipeEnabled: !isLoading});
This solved my problem.