如何从 stack.navigation 外部的组件中使用 navigation.navigate
Posted
技术标签:
【中文标题】如何从 stack.navigation 外部的组件中使用 navigation.navigate【英文标题】:How to use navigation.navigate from a component outside the stack.navigation 【发布时间】:2020-07-24 23:06:19 【问题描述】:我有一个使用 React native 的应用程序,我正在使用 react-navigation (5.2.9)。
我构建了一个 Stack.Navigator,其中有我的屏幕,但我希望 Footer 组件位于外部,以便它在所有屏幕中呈现。问题是,我无法从页脚导航,这是我需要做的,因为页脚有几个按钮应该改变屏幕:
const Stack = createStackNavigator();
const App = () =>
return (
<Provider store=store>
<NavigationContainer>
<Header />
<Stack.Navigator>
<Stack.Screen
name="Home"
component=HomeScreen
options=
headerShown: false
/>
<Stack.Screen
name="Login"
component=LoginScreen
options=
headerShown: false
/>
</Stack.Navigator>
<Footer />
</NavigationContainer>
</Provider>
);
;
如何将导航道具传递给页脚组件?
【问题讨论】:
【参考方案1】:我使用 React 上下文 API 通过全局状态解决了这个问题:
// When enter in the HomeScreen:
const setGlobalNavigation, globalNavigation = useGlobalContext();
const navigation = useNavigation<RemindersNavigationProp>();
useEffect(() =>
if (setGlobalNavigation && !globalNavigation) setGlobalNavigation(navigation);
, [setGlobalNavigation, globalNavigation, navigation]);
// When want to use:
const globalNavigation = useGlobalContext();
const handleNavigate = () =>
globalNavigation.navigate("contactsStack", screen: "newContact" );
【讨论】:
【参考方案2】:从screenOptions
中提取navigation
的简单技巧。
function NavWrapper()
const navigatorRef = useRef<any>();
<Tab.Navigator
screenOptions=( navigation: nav ) => navigatorRef.current = nav
>
<Tab.Screen name="screen1" />
</Tab.Navigator>
【讨论】:
【参考方案3】:试试这个:
创建一个名为:RootNavigation.js 的新文件
// RootNavigation.js
import * as React from 'react';
export const navigationRef = React.createRef();
export function navigate(name, params)
navigationRef.current?.navigate(name, params);
// file where you have the navigation
import navigationRef from './path/to/RootNavigation';
<NavigationContainer ref=navigationRef>
.....
<Footer />
</NavigationContainer>
Footer.js 应该是这样的:
// Footer.js
import React from 'react';
import View, Button from 'react-native';
import * as RootNavigation from './path/to/RootNavigation';
const Footer= () =>
return (
<View>
<Button
title='Go to'
onPress=() =>
RootNavigation.navigate('screenName ', userName: 'Lucy')
/>
</View>
);
;
export default Footer;
有关更多信息,您可以阅读文档。 https://reactnavigation.org/docs/navigating-without-navigation-prop/
【讨论】:
这不是我前一天回答的字面意思吗? 谢谢你,正是我想要的:D 如果我使用导航的文件不是组件/屏幕,这会起作用吗?如,如果它没有被NavigationContainer
包裹?我想要实现的是在收到通知时导航到特定屏幕。 (我为此使用react-native-push-notification
。)但是推送通知的配置不能添加到任何组件中;它应该在一个单独的文件中。
ref.current 始终为空。我将它记录在 setInterval 中并且它没有被初始化。为什么?
好吧,我输入了 navigationRef=navigationRef 而不是 ref=navigationRef。就这样过去了两个小时。天哪:/【参考方案4】:
Stack.Screen
组件之外的组件不接收导航属性。因此,在这种情况下,您必须在页脚组件中使用 refs 获取 NavigationContainer
,如下所示:
-
使用
const myRef = React.createRef()
创建一个引用
将其传递给<NavigationContainer ref=myRef>
,然后
使用该引用进行导航,myRef.current?.navigate(name, params)
。
全部解释here。此处的文档将 ref 的创建分开在一个新文件中,以允许您在没有依赖循环/问题的情况下导入 ref。正如文档所述,您现在可以在任何 js 模块中调用 RootNavigation.navigate('ChatScreen', userName: 'Lucy' );
,而不仅仅是在 react 组件中。
不过,在您的情况下,您不需要单独文件中的 ref。
const Stack = createStackNavigator();
const navigationRef = React.createRef();
const App = () =>
return (
<Provider store=store>
<NavigationContainer ref=navigationRef>
<Header />
<Stack.Navigator>
<Stack.Screen
name="Home"
component=HomeScreen
options=
headerShown: false
/>
<Stack.Screen
name="Login"
component=LoginScreen
options=
headerShown: false
/>
</Stack.Navigator>
<Footer navigationRef=navigationRef/>
</NavigationContainer>
</Provider>
);
;
在<Footer/>
中使用navigationRef.current?.navigate(name, params)
【讨论】:
我发现这比批准的答案更容易理解【参考方案5】:我最终构建了一个名为 screen 的组件,它只会包装 screen 的内容并根据 props 呈现页眉/页脚:
import React from 'react';
import View from 'native-base';
import style from './style';
import Footer from '../../footer';
import Header from '../../header';
const Screen = (
footer,
header,
children,
navigation
) => (
<View style=style.screen>
header && <Header navigation=navigation />
children
footer && <Footer navigation=navigation />
</View>
);
export default Screen;
并像这样包装我的应用程序的屏幕:
<Screen header footer navigation=navigation>
... screen content
</Screen>
如果我不能解决这个问题,我觉得这是最好的方法。
【讨论】:
【参考方案6】:来自文档。 https://reactnavigation.org/docs/connecting-navigation-prop/
import * as React from 'react';
import Button from 'react-native';
import useNavigation from '@react-navigation/native';
function GoToButton( screenName )
const navigation = useNavigation();
return (
<Button
title=`Go to $screenName`
onPress=() => navigation.navigate(screenName)
/>
);
【讨论】:
显然我已经尝试过文档所说的内容,但这只会显示以下错误:找不到navigation.object,您的组件是否在导航器的屏幕内?以上是关于如何从 stack.navigation 外部的组件中使用 navigation.navigate的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Zeppelin 中基于 HadoopGroupProvider 中的组配置角色,使用 Knox 提供基于 SAML 的 SSO?