react-navigation:使用 Expo.addListener 在推送通知中导航的不变违规
Posted
技术标签:
【中文标题】react-navigation:使用 Expo.addListener 在推送通知中导航的不变违规【英文标题】:react-navigation: Invariant Violation on navigating in push notification using Expo.addListener 【发布时间】:2018-09-06 17:42:31 【问题描述】:当我的应用程序收到推送通知时,它应该使用通知数据中的 routeName 参数导航到相应的屏幕。
这一直有效,直到我按照 react-navigation docs 中描述的 NavigationService 模式抽象了我们的导航,并在反应导航问题 here 中充实了更多内容。
我遇到的问题是from react-navigation:Invariant Violation:如果有状态,应该在构造函数中设置
为了解决这个问题,我尝试在 addListener
通话中移动。我已经尝试过 AppcomponentDidMount
、AppWithNavigation ref 回调(这似乎是个坏主意)和 NavigationService 的 setContent
方法。
我尝试了使用 NavigationService 的侦听器的变体,并在 App 中直接使用 NavigationActions.navigate
和 store.dispatch
。
我的理论是导航容器正在发生变化,但导航工作正常,除非应用程序关闭并收到通知。我什至让它在应用程序打开的情况下工作,在这种情况下它确实移动到右屏幕。
我在这里错过了什么?
监听器如下所示:
Notifications.addListener((data: data: NotificationType) =>
const routeName, params = data;
NavigationService.navigate(
routeName,
params,
);
);
NavigationService.js:
import StackActions, NavigationActions from 'react-navigation';
import type NavigationParams, NavigationRoute from 'react-navigation';
import LOGOUT from '../redux/auth';
let _container; // eslint-disable-line
function setContainer(container: Object)
_container = container;
function reset(routeName: NavigationRoute, params?: NavigationParams)
_container.dispatch(
StackActions.reset(
index: 0,
actions: [
NavigationActions.navigate(
routeName,
params,
),
],
),
);
function navigate(routeName: string, params?: NavigationParams)
_container.dispatch(
NavigationActions.navigate(
routeName,
params,
),
);
function goBack(options)
_container.dispatch(NavigationActions.back(options));
function getCurrentRoute(): NavigationRoute | null
if (!_container || !_container.state.nav)
return null;
return _container.state.nav.routes[_container.state.nav.index] || null;
export function logOut()
_container.dispatch(type: LOGOUT);
reset('Welcome');
export default
setContainer,
navigate,
reset,
goBack,
logOut,
;
Navigators.js 的一部分
class AppWithNavigationState extends Component
render()
return (
<React.Fragment>
/* Fix for white icons on white status bar bug on ios */
!isandroid && <StatusBar barStyle="dark-content" />
<RootStack
persistenceKey="NavigationState-2"
ref=navigatorRef => NavigatorService.setContainer(navigatorRef)
/>
</React.Fragment>
);
export default AppWithNavigationState;
【问题讨论】:
【参考方案1】:这是我最终得到的解决方案。不理想,希望尽快升级到 react-navigation 3。我正在使用 renderLoadingExperimental
在加载时渲染 SplashScreen。加载完成后我无法收到通知,因此我在 SplashScreen 中添加了 onUnmount
并在那里处理注册。
class AppWithNavigationState extends Component
render()
return (
<React.Fragment>
<RootStack
persistenceKey="NavigationState-2"
ref=navigatorRef => NavigationService.setContainer(navigatorRef)
renderLoadingExperimental=() => (
<SplashScreen
source="RootStack"
onUnmount=() =>
Notifications.addListener((data) =>
NavigationService.navigate(data.routeName, data.params);
if (Platform.OS === 'android')
Notifications.dismissAllNotificationsAsync();
);
/>
)
/>
</React.Fragment>
);
export default AppWithNavigationState;
【讨论】:
【参考方案2】:我遇到了同样的问题。我的设置与您的非常相似,问题是我在应用导航器完成启动之前在传奇中进行导航作为副作用。检查您是否使用persistenceKey
,如果是,则先前的状态会异步水合,这就是我的问题的原因。
我的主导航器中有一个回调navigationReady
,它位于componentDidMount
,但我认为我必须将其移至实际屏幕以避免该问题。目前我找不到合适的方式来订阅容器在恢复所有内容后调度的操作Navigation / INIT
。
【讨论】:
谢谢,这与我在启动前的问题副作用非常相似。我通过在等待启动完成的启动画面中添加onUnmount
来解决这个问题。将发布代码...以上是关于react-navigation:使用 Expo.addListener 在推送通知中导航的不变违规的主要内容,如果未能解决你的问题,请参考以下文章
退出抽屉内的子堆栈导航器时,如何使用 react-navigation 进入 initialRoute?
如何使用 Expo 清理(重置缓存)React Native。不知道是否缓存问题