12

I have a Tab Navigator inside a Stack Navigator and I want the header title to be dynamically configured as the title of the tab selected. Like there's 3 tabs: Home, Profile, Add Item and I want the header title to be "Home" when in the home tab, "Profile" when in the profile tab.

I tried using onStateChange on the root navigator and setOptions on the tab navigator but onStateChange is only available in the and not in the nested navigators.

Is their anyway I can archieve this?

The navigator config is:

const TabNav = (
   <Tab.Navigator>
      <Tab.Screen name='Home' component={HomeScreen}/>
      <Tab.Screen name='Profile' component={ProfileScreen}/>
      <Tab.Screen name='Add Item' component={AddItemScreen}/>
   </Tab.Navigator>
)

<NavigationContainer>
   <Stack.Navigator>
      <Stack.Screen name='Login' component={LoginScreen}/>
      <Stack.Screen name='App' component={TabNav}/>
   </Stack.Navigator>
</NavigationContainer>
Thiago Nascimento
  • 1,073
  • 2
  • 13
  • 40
  • Have you checked the official docs? https://reactnavigation.org/docs/en/screen-options-resolution.html#setting-parent-screen-options-based-on-child-navigators-state – satya164 Feb 23 '20 at 18:01
  • @satya164 I tried both options in the docs but neither seem to work. The route prop doesn't have `state` key – Thiago Nascimento Feb 24 '20 at 17:27

2 Answers2

9

I had a similar Navigation hierarchy with react-navigation v5 and I wanted to change the Header Title inside a View in the nested TabNavigator. I finally achieved it by getting the parent navigation item of the StackNavigator with dangerouslyGetParent() and then using setOptions().

So here is your minimal Code for one of the three views inside your TabNav:

import React, {useCallback} from 'react';
import { useNavigation, useFocusEffect } from '@react-navigation/native';

const HomeScreen = (props) => {

    // TabNav navigation item
    const navigation = useNavigation();

    // Effect will be triggered everytime the Tab changes 
    //      Mounting is not enough -> Tabs will not be unmount by change
    useFocusEffect(
        useCallback(() => {

            // Get StackNav navigation item
            const stackNavigator = navigation.dangerouslyGetParent();
            if(stackNavigator){

                // Actually set Title
                stackNavigator.setOptions({
                    title: "Home"
                });
            }
        }, [navigation])
    );
    return (
        /* Component Items */
    );
};
Mika
  • 534
  • 5
  • 14
3

From documentation https://reactnavigation.org/docs/screen-options-resolution/

import { getFocusedRouteNameFromRoute } from '@react-navigation/native';

function getHeaderTitle(route) {
  // If the focused route is not found, we need to assume it's the initial screen
  // This can happen during if there hasn't been any navigation inside the screen
  // In our case, it's "Feed" as that's the first screen inside the navigator
  const routeName = getFocusedRouteNameFromRoute(route) ?? 'Feed';

  switch (routeName) {
    case 'Feed':
      return 'News feed';
    case 'Profile':
      return 'My profile';
    case 'Account':
      return 'My account';
  }
}

<Stack.Screen
  name="Home"
  component={HomeTabs}
  options={({ route }) => ({
    headerTitle: getHeaderTitle(route),
  })}
/>
wael
  • 366
  • 1
  • 2
  • 10