Home > OS >  Access Child Screen Props From React Navigation Top Tabs
Access Child Screen Props From React Navigation Top Tabs

Time:04-21

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?

CodePudding user response:

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]);
  
  ...
  }

CodePudding user response:

EDIT

This is one solution that works, but @Kavindu Vindika offered a solution that may be cleaner.

Initial Answer

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.

  • Related