Search code examples
reactjsreact-nativereact-navigation-v5

How do I pass name props from BottomTabs to Stack.Screen headerTitle?


I want to pass the name of the current tab to screen's headerTitle. This is a type of setup that I got from the reactnavigation.org website. This is my code setup.

const Tab = createMaterialBottomTabNavigator();
const Stack = createStackNavigator();

These are my Tabs.

function Tabs() {
    const { colors } = useTheme();
    const theme = useTheme();
    return (
        <Tab.Navigator
            initialRouteName="Home"
            activeTintColor='#fff'
        >
            <Tab.Screen
                name="Home"
                component={Home}
                options={{
                    tabBarLabel: 'Home',
                    tabBarColor: colors.tab,
                    tabBarIcon: ({ color }) => (
                        <Ionicons name="ios-home" color={color} size={26} />
                    ),
                    tabBarBadge: 5,
                }}
            />
            <Tab.Screen
                name="Profile"
                component={Profile}
                options={{
                    tabBarLabel: 'Profile',
                    tabBarColor: colors.tab,
                    tabBarIcon: ({ color }) => (
                        <Ionicons name="ios-person" color={color} size={26} />
                    ),
                }}
            />
        </Tab.Navigator>
    )
}

This is my Stack. I found a line of code on the website which shows passing props to the screen's option, like options={{ headerTitle: props => <LogoTitle {...props} /> }}. I tried the something similar - replaced LogoTitle with Tabs - and I got an error saying Error: Another navigator is already registered for this container.

function AppTabs() {
    const { colors } = useTheme();
    const theme = useTheme();
    return (
        <Stack.Navigator
            screenOptions={{
                headerStyle: {
                    backgroundColor: colors.tab,
                },
                headerTintColor: '#fff',
                headerTitleStyle: {
                    fontWeight: 'bold'
                }
            }}
        >
            <Stack.Screen
                name="Tabs"
                component={Tabs}
                options={({ navigation, route }) => ({
                    headerLeft: () => (
                        <Icon.Button
                            name="ios-menu"
                            size={25}
                            backgroundColor={colors.tab}
                            onPress={() => navigation.openDrawer()}
                        >

                        </Icon.Button>
                    ),
                    // Pass tab name when tab is pressed, here!

                })}
            />
            <Stack.Screen
                name="Contacts"
                component={Phone}
            />
            <Stack.Screen
                name="ContactProfile"
                component={ContactProfile}
            />
        </Stack.Navigator>

    )
}

export default AppTabs;

Solution

  • You can use the getFocusedRouteNameFromRoute function for this:

    // Import getFocusedRouteNameFromRoute
    import {
      NavigationContainer,
      getFocusedRouteNameFromRoute,
    } from '@react-navigation/native';
    
    function getHeaderTitle(route) {
      // In case the focused route is not found, assume it's the first screen
      return getFocusedRouteNameFromRoute(route) ?? 'Home';
    }
    
    function AppTabs() {
      return (
        <Stack.Navigator>
          <Stack.Screen
            name="Tabs"
            component={Tabs}
            options={({route}) => ({
              title: getHeaderTitle(route),
            })}
          />
          <Stack.Screen name="Contacts" component={Phone} />
          <Stack.Screen name="ContactProfile" component={ContactProfile} />
        </Stack.Navigator>
      );
    }
    

    You can read more about it in the documentation: https://reactnavigation.org/docs/screen-options-resolution/#setting-parent-screen-options-based-on-child-navigators-state