我的React Native应用程序希望在用户打开应用程序时将其本地数据与API同步。这应该在用户返回应用程序时发生,而不仅仅是在第一次启动时。基本上,我想要的是相当于AppDelegate的applicationDidBecomeActive
回调,以便我可以在那里运行同步代码。显然,我想在React Native中这样做。
据我所知,根组件上的componentWillMount
/ componentDidMount
回调仅在最初加载应用程序时运行,而不是在用户离开应用程序并稍后返回时运行(没有明确说明)退出应用程序)。
我认为AppState
API会提供此功能,但在这种情况下,其change
侦听器也不会触发。
这看起来很明显,所以我必须错过一些明显的东西。救命啊!
答案 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同步我的应用程序。