React Navigation v5:如何获取子屏幕内父导航器的路由参数
React Navigation v5: How to get route params of the parent navigator inside the child screen
所以我有嵌套的导航器
主要BottomTab.Navigator
- 个人资料底部标签 #1 (Stack.Navigator)
- 配置文件视图(屏幕)
- 关注者(屏幕)
- 以下(顶部 Tab.Navigator)
- 页数(屏幕)
- 组(屏幕)
- Feed 底部选项卡 # 2(堆栈)
- 其他一些 底部选项卡 # 3(堆栈)
问题是当我从 Profile View Screen 导航到 Following Navigator 时,我将一些参数传递给父级 Following Navigator,并且我想要子选项卡屏幕中的所有这些参数 (Pages/Groups)。
但是子选项卡屏幕的路由没有获取传递给父导航器(Following Tab Navigator)的参数
有办法吗?
这是我的代码:
配置文件堆栈
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
};
当我尝试在子选项卡 (Pages/Groups) 中读取这些参数时,这些参数是未定义的
const PageScreen = ({ route }) => {
const { isPublicProfile, firstName } = route.params; // undefined?? Cant read parent's params
...
如有任何帮助,我们将不胜感激。
编辑:我在 github (https://github.com/react-navigation/rfcs/issues/43) 上发现了这个未解决的问题,这还不可能吗?
所以我最终使用了官方 React Navigation documentation 推荐的 React.Context
。请关注官方文档以获取更多信息。
1- Use React context and wrap the navigator with a context provider to pass data to the screens (recommended).
这是我的解决方案:
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);
...
}
所以这是一个不使用上下文的替代 hacky 解决方案;p
但请注意,此渲染回调解决方案是有代价的。阅读 here
Note: By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. 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.
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;
编辑!!! :这仅在您第一次导航到 child object 时有效。可能有一种方法可以每次都重置 child 或 parent,但使用上下文可能更好...
如果有人仍然想要 non-context 解决方案,我相信您可以使用 children 中的 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>
);
您可以轻松地在选项卡导航器中使用 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
所以我有嵌套的导航器
主要BottomTab.Navigator
- 个人资料底部标签 #1 (Stack.Navigator)
- 配置文件视图(屏幕)
- 关注者(屏幕)
- 以下(顶部 Tab.Navigator)
- 页数(屏幕)
- 组(屏幕)
- Feed 底部选项卡 # 2(堆栈)
- 其他一些 底部选项卡 # 3(堆栈)
问题是当我从 Profile View Screen 导航到 Following Navigator 时,我将一些参数传递给父级 Following Navigator,并且我想要子选项卡屏幕中的所有这些参数 (Pages/Groups)。
但是子选项卡屏幕的路由没有获取传递给父导航器(Following Tab Navigator)的参数
有办法吗?
这是我的代码: 配置文件堆栈
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
};
当我尝试在子选项卡 (Pages/Groups) 中读取这些参数时,这些参数是未定义的
const PageScreen = ({ route }) => {
const { isPublicProfile, firstName } = route.params; // undefined?? Cant read parent's params
...
如有任何帮助,我们将不胜感激。
编辑:我在 github (https://github.com/react-navigation/rfcs/issues/43) 上发现了这个未解决的问题,这还不可能吗?
所以我最终使用了官方 React Navigation documentation 推荐的 React.Context
。请关注官方文档以获取更多信息。
1- Use React context and wrap the navigator with a context provider to pass data to the screens (recommended).
这是我的解决方案:
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);
...
}
所以这是一个不使用上下文的替代 hacky 解决方案;p
但请注意,此渲染回调解决方案是有代价的。阅读 here
Note: By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. Using a render callback removes those optimizations. So if you use a render callback, you'll need to ensure that you use
React.memo
orReact.PureComponent
for your screen components to avoid performance issues.
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;
编辑!!! :这仅在您第一次导航到 child object 时有效。可能有一种方法可以每次都重置 child 或 parent,但使用上下文可能更好...
如果有人仍然想要 non-context 解决方案,我相信您可以使用 children 中的 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>
);
您可以轻松地在选项卡导航器中使用 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