Подтвердить что ты не робот

Как определить, когда открыто приложение React Native?

My React Native приложение хочет синхронизировать свои локальные данные с API, когда пользователь открывает приложение. Это должно происходить всякий раз, когда пользователь возвращается в приложение, а не только при первом запуске. По сути, я бы хотел, чтобы это был эквивалент обратного вызова AppDelegate applicationDidBecomeActive, поэтому я могу запустить там код синхронизации. Очевидно, я хотел бы сделать это в React Native.

Насколько я могу судить, обратные вызовы componentWillMount/componentDidMount на корневом компоненте выполняются только при первом загрузке приложения, а не после того, как пользователь покидает приложение и возвращается позже (без явного отказа от приложения).

Я думал, что API AppState предоставит эту функциональность, но его слушатели change также не запускаются в этом случае.

Это похоже на очевидную функциональность, поэтому я должен пропустить что-то очевидное. Помогите!

4b9b3361

Ответ 1

Я исправил это, используя AppStateIOS API вместо AppState. Более поздние работы, как и ожидалось, на устройствах iOS: когда приложение переходит на задний план, происходит событие "change", и снова, когда оно возвращается на передний план. Насколько мне известно, API AppState, похоже, не запускает событие "change" на устройстве iOS, как и в случае 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 changed to...".

Обновление

Похоже, что это было исправлено в React Native в последнее время (с v26). Теперь вы можете использовать AppState, как показано на iOS и Android.

Ответ 2

Я не думаю, что тебе что-то не хватает. Эта функциональность просто не предоставляется реакцией-native из коробки. Возможно, идея заключалась в том, чтобы упростить, поскольку для большинства приложений достаточно выполнить синхронизацию данных, когда приложение вернется на передний план.

Вы можете создать собственный собственный модуль, который предоставляет эту функциональность, или вы можете пойти с простым (вроде хаккой?) решением:

В 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');
  }
}

Я не уверен, что это лучший подход, но он должен работать...

Ответ 3

Думаю, ты уже сам ответил на свой вопрос. Почему бы вам не использовать комбинацию componentWillMount и AppState → 'change'? Это должно охватывать все случаи. Я использую это для синхронизации моего приложения с помощью CodePush.