so I 've got nested navigation, as the code shows. Now I am trying to make the header bar. however, when I change the screens from bottom navigation the header remains the same, no matter on what screen I am(always shoes that I am on Browser screen). Also is the React navigation header the best to create a header bar or is better to create a fully custom one. Thank you
I am expecting that the header title will change in accordance with the page.
const Stack = createStackNavigator();
const Tabs = createMaterialBottomTabNavigator();
const AuthStack = createStackNavigator();
const TabsScreen = () => (
<Tabs.Navigator shifting={true} initialRouteName="Home" activeColor="#fff">
<Tabs.Screen
name="Home"
ponent={Browser}
options={{
tabBarLabel: 'Home',
tabBarColor: '#009387',
tabBarIcon: ({color}) => (
),
}}
/>
<Tabs.Screen
name="Sleep"
ponent={Sleep}
options={{
tabBarLabel: 'Sleep',
tabBarColor: '#694fad',
tabBarIcon: ({color}) => (
),
}}
/>
<Tabs.Screen
name="Settings"
ponent={SettingWithContext}
options={{
tabBarLabel: 'Settings',
tabBarColor: '#694fad',
tabBarIcon: ({color}) => (
),
}}
/>
</Tabs.Navigator>
);
export default CreateStack = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [userToken, setUserToken] = React.useState(null);
const authContext = React.useMemo(() => {
return {
signIn: () => {
setIsLoading(false);
setUserToken('asdf');
},
signUp: () => {
setIsLoading(false);
setUserToken('asdf');
},
signOut: () => {
setIsLoading(false);
setUserToken(null);
},
};
}, []);
React.useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000);
}, []);
if (isLoading) {
return ;
}
return (
<AuthContext.Provider value={authContext}>
{userToken ? (
<Stack.Navigator initialRouteName={Browser}>
<Stack.Screen name="Browser" ponent={TabsScreen} />
<Stack.Screen name="PreScreen" ponent={PreScreen} />
<Stack.Screen name="Player" ponent={Player} />
</Stack.Navigator>
) : (
<AuthStack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={RegisterLogin}>
<AuthStack.Screen name="RegisterLogin" ponent={RegisterLogin} />
<AuthStack.Screen name="Login" ponent={LoginWithContext} />
<AuthStack.Screen name="Register" ponent={RegisterWithContext} />
</AuthStack.Navigator>
)}
</AuthContext.Provider>
);
};
so I 've got nested navigation, as the code shows. Now I am trying to make the header bar. however, when I change the screens from bottom navigation the header remains the same, no matter on what screen I am(always shoes that I am on Browser screen). Also is the React navigation header the best to create a header bar or is better to create a fully custom one. Thank you
I am expecting that the header title will change in accordance with the page.
const Stack = createStackNavigator();
const Tabs = createMaterialBottomTabNavigator();
const AuthStack = createStackNavigator();
const TabsScreen = () => (
<Tabs.Navigator shifting={true} initialRouteName="Home" activeColor="#fff">
<Tabs.Screen
name="Home"
ponent={Browser}
options={{
tabBarLabel: 'Home',
tabBarColor: '#009387',
tabBarIcon: ({color}) => (
),
}}
/>
<Tabs.Screen
name="Sleep"
ponent={Sleep}
options={{
tabBarLabel: 'Sleep',
tabBarColor: '#694fad',
tabBarIcon: ({color}) => (
),
}}
/>
<Tabs.Screen
name="Settings"
ponent={SettingWithContext}
options={{
tabBarLabel: 'Settings',
tabBarColor: '#694fad',
tabBarIcon: ({color}) => (
),
}}
/>
</Tabs.Navigator>
);
export default CreateStack = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [userToken, setUserToken] = React.useState(null);
const authContext = React.useMemo(() => {
return {
signIn: () => {
setIsLoading(false);
setUserToken('asdf');
},
signUp: () => {
setIsLoading(false);
setUserToken('asdf');
},
signOut: () => {
setIsLoading(false);
setUserToken(null);
},
};
}, []);
React.useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000);
}, []);
if (isLoading) {
return ;
}
return (
<AuthContext.Provider value={authContext}>
{userToken ? (
<Stack.Navigator initialRouteName={Browser}>
<Stack.Screen name="Browser" ponent={TabsScreen} />
<Stack.Screen name="PreScreen" ponent={PreScreen} />
<Stack.Screen name="Player" ponent={Player} />
</Stack.Navigator>
) : (
<AuthStack.Navigator
screenOptions={{headerShown: false}}
initialRouteName={RegisterLogin}>
<AuthStack.Screen name="RegisterLogin" ponent={RegisterLogin} />
<AuthStack.Screen name="Login" ponent={LoginWithContext} />
<AuthStack.Screen name="Register" ponent={RegisterWithContext} />
</AuthStack.Navigator>
)}
</AuthContext.Provider>
);
};
Share
Improve this question
asked May 20, 2020 at 9:50
ObsesieObsesie
1884 silver badges17 bronze badges
3 Answers
Reset to default 4If you want to have every tab name to be the top try this: https://reactnavigation/docs/screen-options-resolution/
Check out the getHeaderTitle function and the switch statement below that - it helped me achieve this behavoir.
Because you are using nested navigation, and the stack navigator is the parent one, the top header will remain the same for any navigator inside the TabNavigator.
You might want to create instead a stack navigator inside each tab, so each tab will have its own header title and navigation path.
In another hand, you could try using screen options in order to create some business logic to determine which title you want based on the navigation state.
For example:
const Stack = createStackNavigator();
const Tabs = createMaterialBottomTabNavigator();
const AuthStack = createStackNavigator();
const TabsScreen = () => (
<>
<Tabs.Navigator shifting={true} initialRouteName="Home" activeColor="#fff">
<Tabs.Screen
name="Home"
ponent={Browser}
options={{
tabBarLabel: "Home",
tabBarColor: "#009387",
tabBarIcon: ({ color }) => color,
}}
/>
<Tabs.Screen
name="Sleep"
ponent={Sleep}
options={{
tabBarLabel: "Sleep",
tabBarColor: "#694fad",
tabBarIcon: ({ color }) => color,
}}
/>
<Tabs.Screen
name="Settings"
ponent={SettingWithContext}
options={{
tabBarLabel: "Settings",
tabBarColor: "#694fad",
tabBarIcon: ({ color }) => color,
}}
/>
</Tabs.Navigator>
</>
);
let CreateStack = () => {
const [isLoading, setIsLoading] = React.useState(true);
const [userToken, setUserToken] = React.useState(null);
const authContext = React.useMemo(() => {
return {
signIn: () => {
setIsLoading(false);
setUserToken("asdf");
},
signUp: () => {
setIsLoading(false);
setUserToken("asdf");
},
signOut: () => {
setIsLoading(false);
setUserToken(null);
},
};
}, []);
React.useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000);
}, []);
if (isLoading) {
return;
}
return (
<AuthContext.Provider value={authContext}>
{userToken ? (
<Stack.Navigator initialRouteName={Browser}>
{/* Added the options prop to the Browser screen*/}
<Stack.Screen
name="Browser"
ponent={TabsScreen}
options={({ route }) => ({
headerTitle: getHeaderTitle(route),
})}
/>
<Stack.Screen name="PreScreen" ponent={PreScreen} />
<Stack.Screen name="Player" ponent={Player} />
</Stack.Navigator>
) : (
<AuthStack.Navigator
screenOptions={{ headerShown: false }}
initialRouteName={RegisterLogin}
>
<AuthStack.Screen name="RegisterLogin" ponent={RegisterLogin} />
<AuthStack.Screen name="Login" ponent={LoginWithContext} />
<AuthStack.Screen name="Register" ponent={RegisterWithContext} />
</AuthStack.Navigator>
)}
</AuthContext.Provider>
);
};
/**
* Method to get the route name based on the ponent.
*/
const getHeaderTitle = (route) => {
if (route === "Browser") {
return "Home";
} else if (route === "Sleep") {
return "Sleep"
} else if (route === "Settings") {
return "Settings";
} else {
return route;
}
}
export default CreateStack;
The header is a thing in the stack navigation, not however in the tab-navigation. Your App is using the header of the stack-navigator in which the tab-navigator is nested.
You could nest stack navigators inside your Tab-Navigator to have the header change as you need it to.