I have a BottomTab
navigator nested inside an Stsck
navigator. And the header is configured via Stack screenOptions
:
function AppStackNavigator() {
return (
<Stack.Navigator screenOptions={getScreenOptions}>
<Stack.Screen name="BottomTab" component={BottomTabNavigator}/>
...
</Stack.Navigator>
)
const getScreenOptions = ({route, navigation}) => {
// crazy logic ...
return {
headerLeft: getHeaderLeft,
headerRight: getHeaderRight,
...
}
}
}
And in the BottomTaB
navigator I have an screen called Target
. Notice that the headerShown
is set to false
here.
function BottomTabNavigators() {
return (
<Tab.Navigator
screenOptions={{headerShown: false}}
tabBar={props => <MyTabBar {...props}/>}
>
<Tab.Screen name="Target" component={TargetScreen}/>
</Tab.Navigator>
)
}
In target screen I am overriding the headerRight
of the PARENT navigator, because I need direct interaction between header and a method (methodThatIsOnlyAccessableHere
) which is only accessible inside this screen:
function TargetScreen() {
const methodThatIsOnlyAccessableHere = () => { ... }
useLayoutEffect(() => {
const getHeaderRight = () => {
// call methodThatIsOnlyAccessableHere
...
}
const parentNavigator = navigation.getParent()
parentNavigator.setOptions({
headerRight: getHeaderRight,
})
}, [navigation])
}
Current behaviour:
The top level header configuration (screenOptions
in Stack navigator) is working perfectly. When navigating to Target
screen, the overrided header configuration (using setOptions
) will become active. However, when leaving this screen, this overrided configuration still remains active (Undesired behaviour)
Desired behaviour
When leaving Target
screen, the top level header configuration should become active and the overrided configuration should become effectless.
Why is this my design choice ?
I am always hiding the nested navigator header (the header of the BottomTab
navigator) and configuring the top level (parent) navigator header (Stack
navigator) based on the state of the child navigator. I cannot move the header configuration of Target
screen to the parent because in this case I will not have access to methodThatIsOnlyAccessableHere
.
CodePudding user response:
You would need to update headerRight
again. For instance: use the cleanup of your useLayoutEffect
hook.
useLayoutEffect(() => {
const getHeaderRight = () => {
// call methodThatIsOnlyAccessableHere
...
}
const parentNavigator = navigation.getParent()
parentNavigator.setOptions({
headerRight: getHeaderRight,
})
// cleanup
return () => {
parentNavigator.setOptions({
headerRight: null
})
}
}, [navigation])
CodePudding user response:
I'm assuming your TargetScreen function runs for each route call, to override the parent element whenever possible. If true, you could reset the options at the start of your useLayoutEffect hook, and, again assuming your getParent() call checks for which kind of page youre accessing, it would reset the current page navigation whenever the effect gets called whithout affecting its overriding call.