Managing App Lifecycle
1. Handling App State Changes
| State | Description | Usage |
|---|---|---|
| active | App is in the foreground and visible to the user. | Use for resuming operations, updating UI, starting timers. |
| background | App is in the background but still running. | Use for pausing operations, stopping timers, saving state. |
| inactive | App is in the background but not actively running. | Use for cleaning up resources or preparing for suspension. |
Example: Listening to App State Changes
import { AppState } from 'react-native';
const handleAppStateChange = (nextAppState) => {
if (nextAppState === 'active') {
console.log('App has come to the foreground!');
} else if (nextAppState === 'background') {
console.log('App has gone to the background!');
}
};
AppState.addEventListener('change', handleAppStateChange);
// Don't forget to remove the listener when component unmounts
// AppState.removeEventListener('change', handleAppStateChange);
Note: On iOS, the
inactive state is not emitted. On Android, it might be emitted in some edge cases.
Warning: Do not rely on
AppState for critical app logic as it can be unreliable in some edge cases or device-specific scenarios.
2. Using AppState Events
| Event Name | Description | Notes |
|---|---|---|
| appState | Triggered when the app state changes (e.g., foreground, background) | Useful for managing resources and user experience |
| appStateChange | Event fired when the app transitions between states | Can be used to pause or resume operations |
Example: Listening to AppState Changes
import { AppState } from 'react-native';
const handleAppStateChange = (nextAppState) => {
if (nextAppState === 'active') {
console.log('App is active');
} else if (nextAppState === 'background') {
console.log('App is in background');
} else if (nextAppState === 'inactive') {
console.log('App is inactive');
}
};
AppState.addEventListener('change', handleAppStateChange);
// Clean up listener
const unsubscribe = () => AppState.removeEventListener('change', handleAppStateChange);
Note: The
appState event is not supported on all platforms. On iOS, it may not fire in the background.
3. Detecting App Launch
| Method | Description | Notes |
|---|---|---|
| AppState | Monitors the state of the app (active, background, inactive) | Useful for managing resources and UI updates |
| useAppState | React hook to access AppState in functional components | Provides real-time updates on app state changes |
Example: Using AppState to detect app launch
import { AppState } from 'react-native';\n\nconst handleAppStateChange = (nextAppState) => {\n if (nextAppState === 'active') {\n console.log('App has come to foreground');\n }\n};\n\nAppState.addEventListener('change', handleAppStateChange);\n\n// Cleanup listener when component unmounts\nreturn () => {\n AppState.removeEventListener('change', handleAppStateChange);\n};
Example: Using useAppState hook
import { useAppState } from 'react-native';\n\nconst App = () => {\n const appState = useAppState();\n\n useEffect(() => {\n if (appState === 'active') {\n console.log('App launched or resumed');\n }\n }, [appState]);\n\n return <View></View>;\n};
Note: AppState changes can occur due to various reasons like app switching, device lock, or push notifications. Always handle these transitions gracefully.
4. Handling App Close
| Event | Description | Usage |
|---|---|---|
| appState | Indicates the state of the app (active, background, inactive) | AppState.addEventListener('change', (newState) => { ... }); |
Example: Detecting App Close
import { AppState } from 'react-native';
const handleAppStateChange = (nextAppState) => {
if (nextAppState === 'background') {
console.log('App went to background');
} else if (nextAppState === 'active') {
console.log('App came to foreground');
}
};
AppState.addEventListener('change', handleAppStateChange);
// Clean up listener
const removeListener = () => {
AppState.removeEventListener('change', handleAppStateChange);
};
Note: On iOS, when the app is closed,
appState will be 'inactive' and then 'background'. On Android, it will go directly to 'background'.
5. Using Splash Screen
The splash screen is the first thing users see when they open your app. It's crucial for branding and providing a smooth transition from app launch to the main interface.
| Property | Description | Default Value | Notes |
|---|---|---|---|
| splash.image | Path to the splash screen image file | assets/splash.png |
Must be a PNG or JPG file. Recommended size: 1024x1024px |
| splash.resizeMode | How the image should be resized to fit the screen | contain |
Options: cover, contain, stretch |
| splash.backgroundColor | Background color of the splash screen | #ffffff |
Can be any valid CSS color value |
| splash.showWhenLocked | Whether to show the splash screen while the app is locked | true |
Only affects iOS devices |
Example: Configuring Splash Screen in app.json
{
"expo": {
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
}
}
}
Note: The splash screen is only shown during the app's initial load. Once your app's main component mounts, the splash screen is dismissed automatically.
Warning: If you're using a custom splash screen, make sure to set the
backgroundColor to match your image's background color to prevent any visual artifacts.
Key Points
- Splash screen is shown during app launch
- Can be customized with image, background color, and resize mode
- Image should be at least 1024x1024px for optimal display
- Use
backgroundColorto match your image's background
6. Hiding Splash Screen
After the splash screen is shown, it can be hidden programmatically to reveal the app content.
| Method | Description | Notes |
|---|---|---|
| SplashScreen.hideAsync() | Hides the splash screen asynchronously | Must be called after the app is ready to display content |
Example: Hiding Splash Screen
import * as SplashScreen from 'expo-splash-screen';
// Hide splash screen after app is ready
SplashScreen.hideAsync();
Note: Ensure that the splash screen is hidden only after all necessary resources are loaded to prevent flickering or premature content display.
7. Preventing Auto Hide
Expo's auto-hide behavior can be controlled to prevent the status bar and navigation bar from automatically hiding on Android devices.
| Property | Values | Description |
|---|---|---|
| androidStatusBar.hidden | true / false |
When set to true, the status bar is hidden. Defaults to false. |
| androidStatusBar.translucent | true / false |
If set to true, the status bar is translucent. Defaults to false. |
| androidStatusBar.backgroundColor | Hex color code | Background color of the status bar. Example: #000000. |
Example: Preventing Auto Hide in Android
{
"expo": {
"androidStatusBar": {
"hidden": true,
"translucent": false,
"backgroundColor": "#000000"
}
}
}
Note: On Android, the status bar can be hidden using
StatusBar API from expo-status-bar package. The configuration in app.json is a global setting and affects all screens.
Warning: Hiding the status bar might affect accessibility and usability on some devices. Ensure that your app provides alternative ways to access important controls or information.
8. Implementing Deep Link Handling
| Property | Description | Example |
|---|---|---|
| useDeepLink | Hook to handle deep links in Expo apps | const { scheme } = useDeepLink(); |
| getInitialURL | Get the URL that launched the app | const url = await Linking.getInitialURL(); |
| addEventListener | Listen for deep link events | Linking.addEventListener('url', handleUrl); |
Example: Handling Deep Links in Expo
import { Linking } from 'expo';\n\nconst handleUrl = (event) => {\n const { url } = event;\n console.log('Deep link received:', url);\n};\n\nLinking.addEventListener('url', handleUrl);\n\n// Get initial URL if app was opened via deep link\nLinking.getInitialURL().then((url) => {\n if (url) {\n console.log('Initial URL:', url);\n }\n});
Note: Deep links must be configured in your app's
app.json or app.config.js under the scheme property to work correctly.
Deep Link Configuration
- Add
schemeto your app config for custom URL schemes - Use
Linking.getInitialURL()to retrieve the URL that launched the app - Use
Linking.addEventListener('url', handler)to listen for deep link events
9. Managing Memory Warnings (iOS)
| Property | Description | Notes |
|---|---|---|
| onMemoryWarning | Callback function triggered when iOS memory warning is received | Only available on iOS |
Example: Handling Memory Warnings
import { AppState } from 'react-native';<br><br>const handleMemoryWarning = () => {<br> console.warn('Memory warning received');<br> // Perform cleanup tasks here<br>};<br><br>AppState.addEventListener('memoryWarning', handleMemoryWarning);
Note: Memory warnings are not guaranteed to be sent, but they can occur when the system is under memory pressure.
10. Handling Background Fetch
| Property | Description | Values |
|---|---|---|
| BackgroundFetch | Enables background fetch capabilities | true or false |
| BackgroundFetchInterval | Time interval between fetches in milliseconds | 30000 (30 seconds) |
Example: Configure Background Fetch
import * as BackgroundFetch from 'expo-background-fetch';
const backgroundFetchTask = async () => {
console.log('Background fetch task executed');
// Perform data sync or other operations
};
BackgroundFetch.registerTaskAsync('my-task', {
stopOnTerminate: false,
startOnBoot: true,
periodic: true,
interval: 30000,
});
BackgroundFetch.startTaskAsync('my-task');
Note: Background fetch is subject to OS-level limitations and may not execute at exact intervals.