diff --git a/native/lifecycle/lifecycle-handler.react.js b/native/lifecycle/lifecycle-handler.react.js --- a/native/lifecycle/lifecycle-handler.react.js +++ b/native/lifecycle/lifecycle-handler.react.js @@ -2,11 +2,13 @@ import * as React from 'react'; +import { useIsUserDataReady } from 'lib/hooks/backup-hooks.js'; import { updateLifecycleStateActionType } from 'lib/reducers/lifecycle-state-reducer.js'; import type { LifecycleState } from 'lib/types/lifecycle-state-types.js'; import { useDispatch } from 'lib/utils/redux-utils.js'; +import sleep from 'lib/utils/sleep.js'; -import { addLifecycleListener } from './lifecycle.js'; +import { addLifecycleListener, getCurrentLifecycleState } from './lifecycle.js'; import { appBecameInactive } from '../redux/redux-setup.js'; import { useSelector } from '../redux/redux-utils.js'; @@ -38,7 +40,7 @@ appBecameInactive(); } }, - [lastStateRef, dispatch], + [dispatch], ); React.useEffect(() => { @@ -46,6 +48,33 @@ return () => subscription.remove(); }, [onLifecycleChange]); + React.useEffect(() => { + onLifecycleChange(getCurrentLifecycleState()); + // We update the current state when this component first renders + // in case something happened before PersistGate let us render + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const userDataReady = useIsUserDataReady(); + const prevUserDataReadyRef = React.useRef(userDataReady); + React.useEffect(() => { + void (async () => { + if (prevUserDataReadyRef.current === userDataReady) { + return; + } + prevUserDataReadyRef.current = userDataReady; + if (!userDataReady) { + return; + } + // Backup restore just completed (userDataReady went from false to true) + // Sometimes the backup restore causes "thrashing", which can lead to + // lifecycleState getting out of sync. We refresh after the restore + // concludes to address this. See ENG-11465 + await sleep(100); + onLifecycleChange(getCurrentLifecycleState()); + })(); + }, [userDataReady, onLifecycleChange]); + return null; }, ); diff --git a/native/lifecycle/lifecycle.js b/native/lifecycle/lifecycle.js --- a/native/lifecycle/lifecycle.js +++ b/native/lifecycle/lifecycle.js @@ -18,7 +18,7 @@ } function addLifecycleListener( - listener: (state: ?LifecycleState) => void, + listener: (state: ?(LifecycleState | 'unknown')) => void, ): EventSubscription { if (Platform.OS === 'android') { return addAndroidLifecycleListener(listener); @@ -27,10 +27,10 @@ return NativeAppState.addEventListener('change', listener); } -function getCurrentLifecycleState(): ?string { +function getCurrentLifecycleState(): ?(LifecycleState | 'unknown') { return Platform.OS === 'android' ? currentLifecycleStatus - : NativeAppState.currentState; + : (NativeAppState.currentState: any); } export { addLifecycleListener, getCurrentLifecycleState };