Skip to content

Commit 2f4e9ab

Browse files
Migrate 'State persistance' examples to static API (#1316)
1 parent aded1e8 commit 2f4e9ab

File tree

1 file changed

+201
-4
lines changed

1 file changed

+201
-4
lines changed

versioned_docs/version-7.x/state-persistence.md

Lines changed: 201 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ title: State persistence
44
sidebar_label: State persistence
55
---
66

7+
import Tabs from '@theme/Tabs';
8+
import TabItem from '@theme/TabItem';
9+
710
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.
811

912
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
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
2125
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';
23153
import AsyncStorage from '@react-native-async-storage/async-storage';
24154
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
25207

26208
const 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

77274
This feature is particularly useful in development mode. You can enable it selectively using the following approach:

0 commit comments

Comments
 (0)