How to Persist Navigation State in React Native and React Navigation 5

I am a React / React Native Software Engineer
scale
You might want to save the navigation state in the app, so that the same screen is show after the app is restarted.
In this article we will go through a sample application just to do this.
Snack of the application: https://snack.expo.io/eICO2XnKx
Requirements:
- react-navigation 5
We can use onStateChange and initialState props of the NavigationContainer to implement this functionality.
onStateChange- function notifies of any state changes. We can persist the state in this callback.initialState- This property allows us to pass an initial state to use for navigation state. We can pass the restored state value in this property.
Let’s create two screens HomeScreen and DetailsScreen.
Home.js
// screens/Home.js
import * as React from 'react';
import { View, Text, Button } from 'react-native';
export function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
Details.js
// screens/Details.js
import * as React from 'react';
import { View, Text, Button } from 'react-native';
export function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Home"
onPress={() => navigation.navigate('Home')}
/>
</View>
);
}
Create a stack navigator to navigate between the screens.
AppNavigation.js
*// navigation/AppNavigation.js
*import * as React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { HomeScreen } from '../screens/Home';
import { DetailsScreen } from '../screens/Details';
const Stack = createStackNavigator();
export function AppNavigation(){
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator>
)
}
Let’s now restore and save navigation state in App.js
import * as React from 'react';
import { Linking, Platform, ActivityIndicator } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { NavigationContainer } from '@react-navigation/native';
const PERSISTENCE_KEY = 'NAVIGATION_STATE';
import { AppNavigation } from './navigation/AppNavigation';
export default function App() {
const [isReady, setIsReady] = React.useState(false);
const [initialState, setInitialState] = React.useState();
React.useEffect(() => {
const restoreState = async () => {
try {
const initialUrl = await Linking.getInitialURL();
if (Platform.OS !== 'web' && initialUrl == null) {
// Only restore state if there's no deep link and we're not on web
const savedStateString = await AsyncStorage.getItem(PERSISTENCE_KEY);
const state = savedStateString
? JSON.parse(savedStateString)
: undefined;
if (state !== undefined) {
setInitialState(state);
}
}
} finally {
setIsReady(true);
}
};
if (!isReady) {
restoreState();
}
}, [isReady]);
if (!isReady) {
return <ActivityIndicator/>;
}
return (
<NavigationContainer
initialState={initialState}
onStateChange={(state) =>
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
}>
<AppNavigation/>
</NavigationContainer>
);
}



