Reputation: 1155
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>
Upvotes: 14
Views: 5348
Reputation: 1
In 2024 with expo and react-navigation
v6 it looks like. My navigation was a Stack Navigator nested within a Tab Navigator.
const navigation = useNavigation();
useFocusEffect(
useCallback(() => {
const tabNavigator = navigation.getParent();
if(tabNavigator){
tabNavigator.setOptions({
title: 'Tab + Header Title'
//header only (not tab)
//headerTitle: 'Title Here'
});
}
}, [navigation])
);
Upvotes: 0
Reputation: 386
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),
})}
/>
Upvotes: 5
Reputation: 642
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 */
);
};
Upvotes: 9