如何检测何时打开React Native应用程序?

时间:2016-02-01 22:03:06

标签: react-native

我的React Native应用程序希望在用户打开应用程序时将其本地数据与API同步。这应该在用户返回应用程序时发生,而不仅仅是在第一次启动时。基本上,我想要的是相当于AppDelegate的applicationDidBecomeActive回调,以便我可以在那里运行同步代码。显然,我想在React Native中这样做。

据我所知,根组件上的componentWillMount / componentDidMount回调仅在最初加载应用程序时运行,而不是在用户离开应用程序并稍后返回时运行(没有明确说明)退出应用程序)。

我认为AppState API会提供此功能,但在这种情况下,其change侦听器也不会触发。

这看起来很明显,所以我必须错过一些明显的东西。救命啊!

3 个答案:

答案 0 :(得分:22)

我使用AppStateIOS API代替AppState修复此问题。后者在iOS设备上按预期工作:当应用程序进入后台时,"change"事件将触发,并且当它返回到前台时再次触发。据我所知,AppState API在iOS设备上根本不会触发"change"事件,就像React Native v0.18一样。该项目的约定建议AppState应该是AppStateIOS的跨平台包装器,但这似乎不是这种情况。

以下示例应说明问题:

React.createClass({

  componentDidMount() {
    AppStateIOS.addEventListener('change', state =>
      console.log('AppStateIOS changed to', state)
    )

    AppState.addEventListener('change', state =>
      console.log('AppState changed to', state)
    )
  },

  render() {
    return <View/>
  }

})

将此组件安装到React Native应用程序中时,关闭并打开应用程序时,您将看到“AppStateIOS已更改为...”。根据我的意识,你永远不会看到“AppState改为......”。

<强>更新

最近在React Native中修复了这个问题(截至v26)。您现在可以使用iOS和Android上宣传的AppState

答案 1 :(得分:1)

我不认为你错过了什么。开箱即用的反应本机并不提供此功能。也许这个想法是为了简化,因为对于大多数应用来说,当应用程序返回到前台时,它足以执行数据同步。

您可以创建自己的本机模块来提供此功能,也可以使用简单的(有点hacky?)解决方案:

在AppDelegate中保存对反应根视图的引用:

@interface AppDelegate()
@property (nonatomic, strong) RCTRootView *rootView;
@end

初始化视图时,请设置您的属性并使用它:

self.rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                            moduleName:@"MyApp"
                                     initialProperties:nil
                                         launchOptions:launchOptions];

现在实现AppDelegate方法来处理活动状态,就像在iOS应用程序中那样,并将信息作为道具传递:

-(void)onAppActiveStateChanged:(BOOL)appBecameActive
{
  NSMutableDictionary *newProps = [NSMutableDictionary dictionary];
  if (self.rootView.appProperties != nil) {
    [newProps addEntriesFromDictionary:self.rootView.appProperties];
  }
  newProps[@"appDidBecomeActive"] = @(appBecameActive);
  self.rootView.appProperties = newProps;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
  [self onAppActiveStateChanged:NO];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
  [self onAppActiveStateChanged:YES];
}

在JavaScript方面,在道具改变时做你需要的任何事情:

componentWillReceiveProps(nextProps) {
  if (nextProps.appDidBecomeActive) {
    alert('app did become active');
  }
}

我不确定这是否是最佳方法,但它应该有效...

答案 2 :(得分:0)

我认为你已经回答了自己的问题。为什么不使用componentWillMount和AppState的组合 - &gt; '更改'?这应该涵盖所有情况。我使用它来通过CodePush同步我的应用程序。