React Navigation v5:如何在子屏幕中获取父导航器的路线参数

时间:2020-04-09 17:49:32

标签: javascript reactjs react-native react-navigation react-navigation-v5

所以我有嵌套的导航器

主BottomTab.Navigator

  • 个人资料底部标签1 (Stack.Navigator)
    • 个人资料视图(屏幕)
    • 跟随者(屏幕)
    • 以下(顶部标签导航器)
      • 页面(屏幕)
      • 组(屏幕)
  • Feed 底部标签2 (堆栈)
  • 其他一些底部标签3 (堆栈)

问题是,当我从“配置文件视图”屏幕导航到“关注导航器”时,我将一些参数传递给父“关注导航器”,并且希望在子选项卡“屏幕(页面/组)”中使用所有这些参数。

但是子级选项卡屏幕的路由无法获取传递到父级导航器(以下选项卡导航器)的参数

有办法吗?

这是我的代码: 个人资料堆栈

const ProfileStack = () => (
  <Stack.Navigator
    initialRouteName='profileView'
  >
    <Stack.Screen
      name='profileView'
      component={ProfileScreen}
      options={{
        headerMode: 'screen',
        headerShown: false,
      }}
    />

    <Stack.Screen
      name='followers'
      component={FollowersScreen}
      options={{
        headerTitle: 'Followers',
      }}
    />
    <Stack.Screen
      name='following'
      component={FollowingTabs}
      options={{
        headerTitle: 'Following',
      }}
    />
 </Stack.Navigator>

关注标签

const Tabs = createMaterialTopTabNavigator();
export const FollowingTabs = () => (
  <Tabs.Navigator
    initialRouteName='page'
    lazy
    swipeEnabled
  >
    <Tabs.Screen
      component={PageScreen}
      name='page'
      options={{ tabBarLabel: '2 Pages' }}
    />
    <Tabs.Screen
      component={GroupScreen}
      name='groups'
      options={{ tabBarLabel: '3 Groups' }}
    />
  </Tabs.Navigator>
);

在profileView屏幕中,我试图导航到以下“选项卡”屏幕,并需要按如下所示传递一些参数。

const onPressHandler = () => {
    navigation.navigate('following', **{ isPublicProfile, firstName }**);  // These parameters are passed to route of the following Tabs Navigator
  };

当我尝试在子标签(页面/组)中读取这些参数时,这些参数是未定义的

const PageScreen = ({ route }) => {
  const { isPublicProfile, firstName } = route.params; // undefined?? Cant read parent's params
...

任何帮助将不胜感激。

编辑:我在github(https://github.com/react-navigation/rfcs/issues/43)上发现了这个未解决的问题,这还不可能吗?

4 个答案:

答案 0 :(得分:2)

因此,我最终按照官方React Navigation documentation的建议使用了React.Context。请按照官方文档获取更多信息。

1-使用React上下文,并用上下文提供程序包装导航器,以将数据传递到屏幕(推荐)。

这是我的解决方法:

const DEFAULT_CONTEXT = {
  isPublicProfile: false,
  ...
};

const FollowingTabNavigatorContext = createContext(DEFAULT_CONTEXT);

在“父项之后”选项卡导航器中

const Tabs = createMaterialTopTabNavigator();

export const FollowingTabs = ({ route }) => {
  const { isPublicProfile } = route.params;
  return (
    <FollowingTabNavigatorContext.Provider value={{ isPublicProfile }}>
      <Tabs.Navigator
        initialRouteName='pages'
        lazy
        swipeEnabled
      >
        <Tabs.Screen
          component={PageScreen}
          name='pages'
          options={{ tabBarLabel: '2 Pages' }}
        />
        <Tabs.Screen
          component={GroupScreen}
          name='groups'
          options={{ tabBarLabel: '3 Groups' }}
        />
      </Tabs.Navigator>
    </FollowingTabNavigatorContext.Provider>
  );
};

FollowingTabs.propTypes = propTypes;
FollowingTabs.defaultProps = defaultProps;

最后在我的子选项卡屏幕中:

export const GroupScreen = () => {
  const { isPublicProfile } = useContext(FollowingTabNavigatorContext);
  ...
}

答案 1 :(得分:1)

所以这是不使用上下文的另一种hacky解决方案; p

但是请注意,此渲染回调解决方案需要付费。阅读here

注意:默认情况下,React Navigation将优化应用于屏幕组件,以防止不必要的渲染。使用渲染回调将删除这些优化。因此,如果您使用渲染回调,则需要确保对屏幕组件使用React.memoReact.PureComponent以避免性能问题。

const Tabs = createMaterialTopTabNavigator();

export const FollowingTabs = ({ route }) => {
  const { isPublicProfile } = route.params;
  return (
      <Tabs.Navigator
        initialRouteName='pages'
        lazy
        swipeEnabled
      >
        <Tabs.Screen
          name='pages'
          options={{ tabBarLabel: '2 Pages' }}
        >
          {() => <PageScreen isPublicProfile={isPublicProfile} />}
        </Tabs.Screen>
        <Tabs.Screen
          name='groups'
          options={{ tabBarLabel: '3 Groups' }}
        >
         {() => <GroupScreen isPublicProfile={isPublicProfile} />}
        </Tabs.Screen>
      </Tabs.Navigator>
  );
};

FollowingTabs.propTypes = propTypes;
FollowingTabs.defaultProps = defaultProps;

答案 2 :(得分:0)

编辑!!! :这仅在您第一次导航到子对象时有效。可能有一种方法可以每次都重置孩子或父母,但使用上下文可能更好......

如果有人仍然想要非上下文解决方案,我相信您可以使用子项中的 initialParams 道具来做您想要的。

假设路由有一些参数传递给它。

export const FollowingTabs = ({route}) => (
  <Tabs.Navigator
    initialRouteName='page'
    lazy
    swipeEnabled
  >
    <Tabs.Screen
      component={PageScreen}
      name='page'
      options={{ tabBarLabel: '2 Pages' }}
      initialParams={route.params // Then you can grab these params using the usual route.params in the PageScreen component} 
    />
    <Tabs.Screen
      component={GroupScreen}
      name='groups'
      options={{ tabBarLabel: '3 Groups' }}
    />
  </Tabs.Navigator>
);

答案 3 :(得分:0)

您可以在选项卡导航器中轻松使用 initialParams 并传递道具。 检查此解决方案。

<Stack.Screen name="Settings" >
    { (props) => (
      <Tab.Navigator>
        <Tab.Screen name="Tab1" component={ Tab1 } 
          initialParams={ props.route.params }  // <- pass params from root navigator
        />
        <Tab.Screen name="Tab2" component={ Tab2 } 
          initialParams={ props.route.params } 
        />
      </Tab.Navigator>
      )}
  </Stack.Screen>

参考 https://github.com/react-navigation/rfcs/issues/43#issuecomment-610706264