简体   繁体   English

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

[英]React Navigation v5: How to get route params of the parent navigator inside the child screen

So I have nested navigators所以我有嵌套的导航器

Main BottomTab.Navigator主 BottomTab.Navigator

  • Profile Bottom Tab # 1 (Stack.Navigator)配置文件底部选项卡 #1 (Stack.Navigator)
    • Profile View (Screen)配置文件视图(屏幕)
    • Followers (Screen)追随者(屏幕)
    • Following (Top Tab.Navigator)关注(顶部选项卡导航器)
      • Pages (Screen)页面(屏幕)
      • Groups (Screen)组(屏幕)
  • Feed Bottom Tab # 2 (Stack)纸底部标签 #2 (堆栈)
  • Some other Bottom Tab # 3 (Stack)其他一些底部标签#3 (堆栈)

The problem is when I navigate from Profile View Screen to Following Navigator, I paas some parameters to the parent Following Navigator and I want all of those params in the children tabs Screens (Pages/Groups).问题是当我从 Profile View Screen 导航到 Follow Navigator 时,我将一些参数传递给父 Follow Navigator,并且我希望所有这些参数都在子选项卡屏幕(页面/组)中。

But the route of the children tab screens do not get the parameters which are passed to the parent navigator (Following Tab Navigator)但是子标签屏幕的路由没有得到传递给父导航器的参数(Following Tab Navigator)

Is there a way to do that?有没有办法做到这一点?

Here's my code: Profile Stack这是我的代码:配置文件堆栈

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>

FollowingTabs关注标签

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

From the profileView Screen Im trying to navigate to following Tabs Screen and need to pass some parameters as follows.从 profileView 屏幕我试图导航到以下选项卡屏幕,并且需要传递一些参数,如下所示。

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

And when I try to read these parameters in children tabs (Pages/Groups) these are undefined当我尝试在子选项卡(页面/组)中读取这些参数时,这些参数是未定义的

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

Any help would be appreciated.任何帮助,将不胜感激。

Edit: I found this open Issue on github ( https://github.com/react-navigation/rfcs/issues/43 ) Is this not possible yet?编辑:我在 github ( https://github.com/react-navigation/rfcs/issues/43 )上发现了这个未解决的问题 这还不可能吗?

So I ended up use React.Context as recommended by official React Navigation documentation .所以我最终按照官方 React Navigation 文档的推荐使用了React.Context Please Follow the official documentation for more information.请关注官方文档以获取更多信息。

1- Use React context and wrap the navigator with a context provider to pass data to the screens (recommended). 1- 使用 React 上下文并使用上下文提供程序包装导航器以将数据传递到屏幕(推荐)。

Here's my solution:这是我的解决方案:

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

const FollowingTabNavigatorContext = createContext(DEFAULT_CONTEXT);

In Parent Following Tab Navigator在父级以下选项卡导航器中

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;

And Finally In my the child Tab Screens:最后在我的子标签屏幕中:

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

So Here's an alternate hacky solution without using context;p所以这是一个不使用上下文的替代hacky解决方案;p

BUT Beware this render callback solution comes with a cost.但要注意这个渲染回调解决方案是有代价的。 Read here 在这里阅读

Note: By default, React Navigation applies optimizations to screen components to prevent unnecessary renders.注意:默认情况下,React Navigation 会对屏幕组件进行优化,以防止不必要的渲染。 Using a render callback removes those optimizations.使用渲染回调会删除这些优化。 So if you use a render callback, you'll need to ensure that you use React.memo or React.PureComponent for your screen components to avoid performance issues.所以如果你使用渲染回调,你需要确保你的屏幕组件使用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;

Edit:., .编辑:。, 。 This only works the first time you navigate to the child object.这仅在您第一次导航到子 object 时有效。 There's probably a way to reset the child or parent every time.可能有一种方法可以每次都重置孩子或父母。 but using context is probably better...但使用上下文可能更好......

If anyone is still wanting a non-context solution, I believe you can use the initialParams prop in the children to do what you're looking for.如果有人仍然想要一个非上下文解决方案,我相信你可以使用孩子们的initialParams道具来做你正在寻找的事情。

Assume route has some params passed to it.假设路由有一些参数传递给它。

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

You can easily use initialParams in tab navigator and pass the props.您可以轻松地在选项卡导航器中使用 initialParams 并传递道具。 Check this solution.检查此解决方案。

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM