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.navigatestore.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-navigate 中动态选择初始路由名称

退出抽屉内的子堆栈导航器时,如何使用 react-navigation 进入 initialRoute?

如何使用 Expo 清理(重置缓存)React Native。不知道是否缓存问题

如果您使用深度链接,Expo web 使用错误的基本 uri 加载资产

无法解决反应导航/核心

StackNavigator 标题未在最简单的示例中显示