@@ -4,6 +4,9 @@ title: State persistence
44sidebar_label : State persistence
55---
66
7+ import Tabs from '@theme/Tabs ';
8+ import TabItem from '@theme/TabItem ';
9+
710You might want to save the user's location in the app, so that they are immediately returned to the same location after the app is restarted.
811
912This is especially valuable during development because it allows the developer to stay on the same screen when they refresh the app.
@@ -15,13 +18,192 @@ To be able to persist the [navigation state](navigation-state.md), we can use th
1518- ` onStateChange ` - This prop notifies us of any state changes. We can persist the state in this callback.
1619- ` initialState ` - This prop allows us to pass an initial state to use for [ navigation state] ( navigation-state.md ) . We can pass the restored state in this prop.
1720
18- <samp id =" state-persistance " />
21+ <Tabs groupId =" config " queryString =" config " >
22+ <TabItem value =" static " label =" Static " default >
1923
20- ``` js
24+ ``` js name="Persisting the navigation state" snack version=7 dependencies=@react-native-async-storage/async-storage
2125import * as React from ' react' ;
22- import { Linking , Platform } from ' react-native' ;
26+ // codeblock-focus-start
27+ import { Platform , View , Linking } from ' react-native' ;
28+ import AsyncStorage from ' @react-native-async-storage/async-storage' ;
29+ import {
30+ useNavigation ,
31+ createStaticNavigation ,
32+ } from ' @react-navigation/native' ;
33+ // codeblock-focus-end
34+ import { Button } from ' @react-navigation/elements' ;
35+ import { createBottomTabNavigator } from ' @react-navigation/bottom-tabs' ;
36+ import { createNativeStackNavigator } from ' @react-navigation/native-stack' ;
37+
38+ function A () {
39+ return < View / > ;
40+ }
41+
42+ function B () {
43+ const navigation = useNavigation ();
44+
45+ return (
46+ < View style= {{ flex: 1 , alignItems: ' center' , justifyContent: ' center' }}>
47+ < Button onPress= {() => navigation .navigate (' C' )}> Go to C < / Button>
48+ < / View>
49+ );
50+ }
51+
52+ function C () {
53+ const navigation = useNavigation ();
54+
55+ return (
56+ < View style= {{ flex: 1 , alignItems: ' center' , justifyContent: ' center' }}>
57+ < Button onPress= {() => navigation .navigate (' D' )}> Go to D < / Button>
58+ < / View>
59+ );
60+ }
61+
62+ function D () {
63+ return < View / > ;
64+ }
65+
66+ const HomeStackScreen = createNativeStackNavigator ({
67+ screens: {
68+ A : A ,
69+ },
70+ });
71+
72+ const SettingsStackScreen = createNativeStackNavigator ({
73+ screens: {
74+ B : B ,
75+ C : C ,
76+ D : D ,
77+ },
78+ });
79+
80+ // codeblock-focus-start
81+
82+ const PERSISTENCE_KEY = ' NAVIGATION_STATE_V1' ;
83+
84+ export default function App () {
85+ const [isReady , setIsReady ] = React .useState (Platform .OS === ' web' ); // Don't persist state on web since it's based on URL
86+ const [initialState , setInitialState ] = React .useState ();
87+
88+ React .useEffect (() => {
89+ const restoreState = async () => {
90+ try {
91+ const initialUrl = await Linking .getInitialURL ();
92+
93+ if (Platform .OS !== ' web' && initialUrl == null ) {
94+ const savedState = await AsyncStorage .getItem (PERSISTENCE_KEY );
95+ const state = savedState ? JSON .parse (savedState) : undefined ;
96+
97+ if (state !== undefined ) {
98+ setInitialState (state);
99+ }
100+ }
101+ } finally {
102+ setIsReady (true );
103+ }
104+ };
105+
106+ if (! isReady) {
107+ restoreState ();
108+ }
109+ }, [isReady]);
110+
111+ if (! isReady) {
112+ return null ;
113+ }
114+ const Tab = createBottomTabNavigator ({
115+ screens: {
116+ Home: {
117+ screen : HomeStackScreen,
118+ options: {
119+ headerShown: false ,
120+ tabBarLabel: ' Home!' ,
121+ },
122+ },
123+ Settings: {
124+ screen : SettingsStackScreen,
125+ options: {
126+ headerShown: false ,
127+ tabBarLabel: ' Settings!' ,
128+ },
129+ },
130+ },
131+ });
132+ const Navigation = createStaticNavigation (Tab);
133+
134+ return (
135+ < Navigation
136+ initialState= {initialState}
137+ onStateChange= {(state ) =>
138+ AsyncStorage .setItem (PERSISTENCE_KEY , JSON .stringify (state))
139+ }
140+ / >
141+ );
142+ }
143+ // codeblock-focus-end
144+ ```
145+
146+ </TabItem >
147+ <TabItem value =" dynamic " label =" Dynamic " default >
148+
149+ ``` js name="Persisting the navigation state" snack version=7 dependencies=@react-native-async-storage/async-storage
150+ import * as React from ' react' ;
151+ // codeblock-focus-start
152+ import { Platform , View , Linking } from ' react-native' ;
23153import AsyncStorage from ' @react-native-async-storage/async-storage' ;
24154import { NavigationContainer } from ' @react-navigation/native' ;
155+ // codeblock-focus-end
156+ import { Button } from ' @react-navigation/elements' ;
157+ import { createBottomTabNavigator } from ' @react-navigation/bottom-tabs' ;
158+ import { createNativeStackNavigator } from ' @react-navigation/native-stack' ;
159+
160+ const Tab = createBottomTabNavigator ();
161+ const HomeStack = createNativeStackNavigator ();
162+ const SettingsStack = createNativeStackNavigator ();
163+
164+ function A () {
165+ return < View / > ;
166+ }
167+
168+ function B ({ navigation }) {
169+ return (
170+ < View style= {{ flex: 1 , alignItems: ' center' , justifyContent: ' center' }}>
171+ < Button onPress= {() => navigation .navigate (' C' )}> Go to C < / Button>
172+ < / View>
173+ );
174+ }
175+
176+ function C ({ navigation }) {
177+ return (
178+ < View style= {{ flex: 1 , alignItems: ' center' , justifyContent: ' center' }}>
179+ < Button onPress= {() => navigation .navigate (' D' )}> Go to D < / Button>
180+ < / View>
181+ );
182+ }
183+
184+ function D () {
185+ return < View / > ;
186+ }
187+
188+ function HomeStackScreen () {
189+ return (
190+ < HomeStack .Navigator >
191+ < HomeStack .Screen name= " A" component= {A } / >
192+ < / HomeStack .Navigator >
193+ );
194+ }
195+
196+ function SettingsStackScreen () {
197+ return (
198+ < SettingsStack .Navigator >
199+ < SettingsStack .Screen name= " B" component= {B } / >
200+ < SettingsStack .Screen name= " C" component= {C } / >
201+ < SettingsStack .Screen name= " D" component= {D } / >
202+ < / SettingsStack .Navigator >
203+ );
204+ }
205+
206+ // codeblock-focus-start
25207
26208const PERSISTENCE_KEY = ' NAVIGATION_STATE_V1' ;
27209
@@ -66,12 +248,27 @@ export default function App() {
66248 AsyncStorage .setItem (PERSISTENCE_KEY , JSON .stringify (state))
67249 }
68250 >
69- {/* ... */ }
251+ < Tab .Navigator screenOptions= {{ headerShown: false }}>
252+ < Tab .Screen
253+ name= " Home"
254+ component= {HomeStackScreen}
255+ options= {{ tabBarLabel: ' Home!' }}
256+ / >
257+ < Tab .Screen
258+ name= " Settings"
259+ component= {SettingsStackScreen}
260+ options= {{ tabBarLabel: ' Settings!' }}
261+ / >
262+ < / Tab .Navigator >
70263 < / NavigationContainer>
71264 );
72265}
266+ // codeblock-focus-end
73267```
74268
269+ </TabItem >
270+ </Tabs >
271+
75272### Development Mode
76273
77274This feature is particularly useful in development mode. You can enable it selectively using the following approach:
0 commit comments