AppState.currentState is 'active' in the foreground and 'background' when the user is in another app, on the home screen or, on Android, in another activity such as a system autofill picker; iOS adds 'inactive' for the moment in between. The change event reports transitions, iOS adds memoryWarning, and Android adds blur and focus for moments when the app is visible but not in use, such as a pulled-down notification shade:
const last = useRef(AppState.currentState);
useEffect(() => {
const subs = [
AppState.addEventListener('change', (next) => {
if (last.current === 'background' && next === 'active') console.log('back in front');
console.log(`change: ${last.current} -> ${next}`);
last.current = next;
}),
AppState.addEventListener('blur', () => console.log('blur')), // Android only
AppState.addEventListener('focus', () => console.log('focus')), // Android only
];
return () => subs.forEach((s) => s.remove());
}, []);Pulling the shade down and up (adb shell cmd statusbar expand-notifications, then collapse), pressing Home and relaunching the app logged:
LOG blur LOG focus LOG change: active -> background LOG blur LOG back in front LOG change: background -> active LOG focus
The shade changed only focus. Use change to pause timers and refresh stale data on return, and keep the handler short: the OS may suspend a backgrounded app at any moment.