React Navigation v5 setOptions不起作用

时间:2020-09-07 04:46:32

标签: react-native react-navigation

我正在尝试从组件内部的堆栈屏幕设置导航选项,因为我需要使用屏幕上的特定操作来渲染右侧标题按钮。问题是它不起作用。 我使用的结构如下:

-StackNavigator
  -MaterialTopTabNavigator
    -tab1
    -tab2
    -tab3

当前代码:

//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>

我的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>
)

我已经尝试按照文档建议使用useLayoutEffect设置组件内部的选项,也尝试使用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:我知道隐藏标头并为标头使用自定义组件可以解决此问题,但是我想知道为什么navigation.setOptions无法正常工作。

任何帮助,任何想法将不胜感激,谢谢!

3 个答案:

答案 0 :(得分:1)

标签导航器本身没有任何标题。儿童内部的TopTab.Navigator将无法访问父级导航,即Stack.Navigator。您要么需要将父导航的实例传递给选项卡的子项,要么从堆栈中隐藏标题,然后在选项卡子项中创建自己的标题组件。另一个选择是将一个侦听器附加到选项卡屏幕,如下所示,然后您可以更新父堆栈的标题。

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',
            });
        },
    }}
/>

您可以找到更多详细信息here

答案 1 :(得分:0)

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]);

答案 2 :(得分:0)

This 帮助了我。 我通过 dangerouslyGetParent() 方法访问父堆栈导航器并设置它的选项来解决它。

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>
      ),
    });
  }
}, []);