@@ -4,6 +4,9 @@ title: State persistence
4
4
sidebar_label : State persistence
5
5
---
6
6
7
+ import Tabs from '@theme/Tabs ';
8
+ import TabItem from '@theme/TabItem ';
9
+
7
10
You 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.
8
11
9
12
This 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
15
18
- ` onStateChange ` - This prop notifies us of any state changes. We can persist the state in this callback.
16
19
- ` 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.
17
20
18
- <samp id =" state-persistance " />
21
+ <Tabs groupId =" config " queryString =" config " >
22
+ <TabItem value =" static " label =" Static " default >
19
23
20
- ``` js
24
+ ``` js name="Persisting the navigation state" snack version=7 dependencies=@react-native-async-storage/async-storage
21
25
import * 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' ;
23
153
import AsyncStorage from ' @react-native-async-storage/async-storage' ;
24
154
import { 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
25
207
26
208
const PERSISTENCE_KEY = ' NAVIGATION_STATE_V1' ;
27
209
@@ -66,12 +248,27 @@ export default function App() {
66
248
AsyncStorage .setItem (PERSISTENCE_KEY , JSON .stringify (state))
67
249
}
68
250
>
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 >
70
263
< / NavigationContainer>
71
264
);
72
265
}
266
+ // codeblock-focus-end
73
267
```
74
268
269
+ </TabItem >
270
+ </Tabs >
271
+
75
272
### Development Mode
76
273
77
274
This feature is particularly useful in development mode. You can enable it selectively using the following approach:
0 commit comments