Reputation: 1340
I'm trying to set the navigation options from my stack screen inside my component since I need to render a right header button with specific actions from my screen. Problem is that it is not working. The structure I'm using is as follows:
-StackNavigator
-MaterialTopTabNavigator
-tab1
-tab2
-tab3
Current code:
//My navigation
<NavigationContainer initialState={initialState} ref={ref}>
<Stack.Navigator screenOptions={{ headerShown: false }}>
//some other Stacks
<Stack.Screen
name="Detail"
component={DetailTabScreen}
options={{
headerShown: true, //header works ok
headerRight: () => ( //this would work
<View style={{backgroundColor: 'red', width: 100}}/>
)
}}
/>
</Stack.Navigator>
</NavigationContainer>
My DetailTabScreen:
const TopTab = createMaterialTopTabNavigator()
const DetailTabScreen = () => (
<StoreProvider>
<SafeAreaView style={{ flex: 1 }}>
<TopTab.Navigator
tabBarOptions={{
...options
}}
>
<TopTab.Screen
name="PlanDetail"
component={PlanDetail}
options={{
tabBarLabel: ({ color }: TabBarLabelProps) => (
<Text>Detalles</Text>
),
}}
/>
<TopTab.Screen
name="PlanChat"
component={PlanChat}
options={{
tabBarLabel: ({ color }: TabBarLabelProps) => (
<Text>Chat</Text>
),
}}
/>
<TopTab.Screen
name="Participants"
component={Participants}
options={{
tabBarLabel: ({ color }: TabBarLabelProps) => (
<Text>Participantes</Text>
),
}}
/>
</TopTab.Navigator>
</SafeAreaView>
</StoreProvider>
)
I already have tried setting the options inside the component as the docs suggests using the useLayoutEffect
, also tried using the useEffect
:
useLayoutEffect(() => {
props.navigation.setOptions({
headerRight: () => (//does not work
<TouchableOpacity
onPress={() => console.warn('This is a button!')}
style={{marginRight:16}}
>
<Icon name={Platform.OS === 'ios' ? 'share-apple' : 'share-google'} type="EvilIcons" style={{ color: colors.darkGreen, marginright: 16 }} />
</TouchableOpacity>
),
});
}, []);
PS: I know that hiding the header and using a custom component for my header would work as a work around but I want to know why navigation.setOptions
is not working.
Any help, any ideas would be appreciated, thanks!
Upvotes: 3
Views: 5041
Reputation: 1032
This helped me out. I solved it by accessing parent stack navigator via dangerouslyGetParent() method and setting its options.
useLayoutEffect(() => {
const stackNavigator = props.navigation.dangerouslyGetParent(); // this is what you need
if (stackNavigator) {
stackNavigator.setOptions({
headerRight: () => (
<TouchableOpacity
onPress={() => console.warn("This is a button!")}
style={{ marginRight: 16 }}
>
<Icon
name={Platform.OS === "ios" ? "share-apple" : "share-google"}
type="EvilIcons"
style={{ color: colors.darkGreen, marginright: 16 }}
/>
</TouchableOpacity>
),
});
}
}, []);
Upvotes: 5
Reputation: 545
function SomeScreen({navigation}) {
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => <TouchableOpacity
onPress={() => console.warn('This is a button!')}
style={{ marginRight: 16 }}>
<Icon name={Platform.OS === 'ios' ? 'share-apple' : 'share-google'}
type="EvilIcons" style={{ color: colors.darkGreen, marginright: 16 }} />
</TouchableOpacity>
});
}, [navigation]);
}
Upvotes: 0
Reputation: 2135
A tab navigator itself doesn't have any header. Children's inside TopTab.Navigator won't have access to parent navigation ie Stack.Navigator. You either need to pass an instance of parent navigation to the children of tabs or hide the header from the stack and create your own header component inside tab children. Another option is to attach a listener to tab screen like below and then you can update the header of the parent stack.
const DetailTabScreen = (props) => {
....
<TopTab.Screen
name="PlanDetail"
component={PlanDetail}
options={{
tabBarLabel: ({ color }: TabBarLabelProps) => (
<Text>Detalles</Text>
),
}}
listeners={{
tabPress: (e) => {
// Prevent default action
props.navigation.setOptions({
title: 'PlanDetail',
});
},
}}
/>
You can find more details here
Upvotes: 3