react-navigation:使用Expo.addListener在推送通知中进行导航时不变

时间:2018-09-06 17:42:32

标签: react-native push-notification react-navigation expo

当我的应用程序收到推送通知时,应使用通知数据中的routeName参数导航到适当的屏幕。

这一直有效,直到我按照react-navigation docs中所述的NavigationService模式抽象出导航,并在反应导航问题here中充实了。

我遇到的问题是from react-navigation不变违反:如果有状态,应在构造函数中设置

为解决此问题,我尝试绕过addListener调用。我已经尝试了App componentDidMount,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;

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。我的设置与您的设置非常相似,问题是在应用程序导航器完成启动之前,我作为传奇人物进行了导航。检查您是否正在使用persistenceKey,如果是,则先前的状态会被异步水化,这是我遇到问题的原因。 我在navigationReady的主导航器中有一个回调componentDidMount,但是我认为我必须将其移至实际屏幕上才能避免该问题。目前,在还原所有内容之后,我找不到合适的方法来订阅由容器分派的操作Navigation / INIT

答案 1 :(得分:0)

这是我最终得到的解决方案。这并不理想,因此希望尽快升级到反应导航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;