我的app.js
文件看起来像这样
export default class App extends React.Component {
render() {
return (
<Root style={{
flex: 1
}}>
<FcmHandler/>
</Root>
)
}
}
Root
组件是整个应用程序所在的位置以及所有功能,FcmHandler
是我处理与通知相关的功能的地方等。FcmHandler
我有一个方法在点击通知时收到回调,在此回调中我需要根据通知点击导航到应用中的特定屏幕。
问题是使用FcmHandler
组件上方的当前代码,甚至从未初始化。
如果我尝试这样的话
export default class App extends React.Component {
render() {
return (
<View style={{
flex: 1
}}>
<Root/>
<FcmHandler/>
</View>
)
}
}
FcmHandler
组件被调用,但我无权访问位于<Root/>
组件内的导航道具。
<Root/>
组件包含以下内容
const ArticleStack = StackNavigator(
{
...
}
);
const SettingsStack = StackNavigator({
...
});
export const Root = StackNavigator({
Articles: {
screen: ArticleStack
},
Settings: {
screen: SettingsStack
},
}, {
mode: 'modal',
headerMode: 'none'
});
我想要实现的基本目标是,当点击通知时,无论应用程序当前在哪个屏幕上,我都应该能够导航到特定屏幕。我不想在我拥有的每个屏幕组件中编写导航代码,这似乎是多余的。
答案 0 :(得分:2)
您可以按this official guide创建导航服务。然后使用FcmHandler
中的导航服务代替navigation
道具。这样就不需要将FcmHandler
作为导航器的子项。
如果您使用的是redux或mobx,最好将导航状态移至商店以便于访问。对于redux,有一个official integration guide。对于mobx,您可以尝试this。
答案 1 :(得分:1)
对于react-navigation
用户,一种非常酷的方式是创建自己的导航服务
您可以在初始化导航商店期间初始化导航服务模块,如docs
中所述 <AppNavigator navigation={addNavigationHelpers({
dispatch: this.props.dispatch,
state: this.props.nav,
addListener,
})} />
// Just add another line to config the navigator object
NavigationService.configNavigator(dispatch) <== This is the important part
<强> NavigationService.js 强>
import { NavigationActions } from 'react-navigation'
let config = {}
const configNavigator = nav => {
config.navigator = nav
}
const reset = (routeName, params) => {
let action = NavigationActions.reset({
index: 0,
key: null,
actions: [
NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName,
params,
}),
],
})
config.navigator(action)
}
const navigate = (routeName, params) => {
let action = NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName,
params,
})
config.navigator(action)
}
const navigateDeep = actions => {
let action = actions.reduceRight(
(prevAction, action) =>
NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName: action.routeName,
params: action.params,
action: prevAction,
}),
undefined
)
config.navigator(action)
}
const goBack = () => {
if (config.navigator) {
let action = NavigationActions.back({})
config.navigator(action)
}
}
export default {
configNavigator,
navigateDeep,
navigate,
reset,
goBack,
}
解释:
config
会在navigator's dispatch
被初始化时初始化redux-navigation
对象,因此您可以dispatch any navigation action
, wrt < em>服务组件。
使用强>
NavigationServices.navigate('ScreenName')
<强>更新强>
React Navigation现在提供HOC wrapper
withNavigation
,将导航道具传递给包装组件。
当你无法直接将导航道具传递给组件,或者在深层嵌套的孩子的情况下不想传递它时,它很有用。
docs中提到了用法。
答案 2 :(得分:0)
经过一番研究,我发现最简单的方法就是遵循他们的official documentation:
RootNavigation.js
文件夹中创建了一个./misc
文件;
import * as React from 'react';
export const navigationRef = React.createRef();
export function navigate(name, params) {
navigationRef.current?.navigate(name, params);
}
import React from 'react'
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { navigationRef } from './misc/rootNavigation'; <- navigationRef is imported
…
const Stack = createStackNavigator();
function App() {
return (
<Provider store={store}>
<NavigationContainer ref={navigationRef}> <— reference to navigationRef
<Stack.Navigator>
…
<Stack.Screen
name="Screen"
component={Screen}
options={{
title: “Hello”,
headerLeft: () => <ScreenButton/>
}} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
}
export default App
ScreenButton
组件中调用了它
import React, { Component } from 'react'
…
import * as RootNavigation from '../misc/rootNavigation'; <—- imported
class RoomButton extends Component {
constructor(props) {
super(props)
}
render() {
return (
<TouchableOpacity onPress={
() => {RootNavigation.navigate( 'RoomSelectorScreen' ) <—- called here
…
</TouchableOpacity>
)
}
}