2

My React navigation version has just upgraded from v4 to v5.

Here is my nested navigation :

Stack Navigation

  • Main (Tab.Navigator)

    • home (Stack Navigation)
      • screen A (initial route screen)
      • screen B (screen)
    • settings (Stack Navigation)
  • Web (Tab.Navigator)

I have put a language switch button in screen A headerRight() and handle the language state with react-redux.

this.props.navigation.setOptions({ 
        title: I18n.t("ScreenA"),
        headerRight: () => (< LangSwitchButton />),
    })

In tabNavigator.js,

< Tab.Screen 
   name="TabA"
   component={homeScreen} 
   options={tabBarLabel: I18n.t("tabA")}
   listeners={({ navigation, route }) => ({navigation.navigate("home"))} 
/> 

In navigation v4, the language can be switched in real time with static navigationOptions. But in navigation v5, this.props.navigation.setOptions cannot update the state of tabBarLabel. Only tap to other screen and back to the screen A can update the language state.

My current approach is to put this.props.navigation.setOptions part inside render(), language switch works for the header and main content, but the language of the tabBarLabel still not updated in real-time.

Is there any ways to update the tabBarLabel through setOptions in screen level?

Thank you.

Amy K
  • 21
  • 3
  • I had a similar-looking issue: I had all of the screens in a fragment component, which isn't allowed to use props. I used a hook in the component, but because there were no props to be updated, the component did not re-render. It seems weird that React doesn't warn when you use a hook in a fragment. – Nate Glenn Mar 10 '23 at 05:57

2 Answers2

0

Looks like this code doesn't trigger a re-render:

options={tabBarLabel: I18n.t("tabA")}

This will work automatically if it could trigger a re-render. I'm not sure how your I18n.t function is implemented, but if the translation value is from redux store, then you'll need to build a hook using useSelector which can trigger a re-render. Something like:

const useI18n() {
  const language = useSelector(store => store.language);

  return (text) => I18n.t(text, language);
}

// And then use it like

const t = useI18n();

// ...

options={{ tabBarLabel: t("tabA") }}

This is pseudo-code just to give an idea

In navigation v4, the language can be switched in real time with static navigationOptions. But in navigation v5, this.props.navigation.setOptions cannot update the state of tabBarLabel. Only tap to other screen and back to the screen A can update the language state.

This is not true. In React Navigation 4, it's not possible to dynamically update options. For v5, setOptions should work (tho not correct approach). Are you sure the setOptions is getting called (and from correct place)?

satya164
  • 9,464
  • 2
  • 31
  • 42
0

You could try to set like

<Tab.Screen name="TabA" component={homeScreen} options={() => {tabBarLabel: translate} />