Skip to main content
Version: 6.x

状态持久化

你可能希望在应用中保存用户的位置,以便在应用重新启动后他们立即返回到同一位置。

¥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.

这在开发过程中特别有价值,因为它允许开发者在刷新应用时保持在同一屏幕上。

¥This is especially valuable during development because it allows the developer to stay on the same screen when they refresh the app.

用法

¥Usage

为了能够持久化 导航状态,我们可以使用容器的 onStateChangeinitialState 属性。

¥To be able to persist the navigation state, we can use the onStateChange and initialState props of the container.

  • onStateChange - 该属性会通知我们任何状态变化。我们可以在这个回调中保留状态。

    ¥onStateChange - This prop notifies us of any state changes. We can persist the state in this callback.

  • initialState - 该属性允许我们传递用于 导航状态 的初始状态。我们可以在这个 prop 中传递恢复的状态。

    ¥initialState - This prop allows us to pass an initial state to use for navigation state. We can pass the restored state in this prop.

import * as React from 'react';
import { Linking, Platform } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { NavigationContainer } from '@react-navigation/native';

const PERSISTENCE_KEY = 'NAVIGATION_STATE_V1';

export default function App() {
const [isReady, setIsReady] = React.useState(Platform.OS === 'web'); // Don't persist state on web since it's based on URL
const [initialState, setInitialState] = React.useState();

React.useEffect(() => {
const restoreState = async () => {
try {
const initialUrl = await Linking.getInitialURL();

if (initialUrl == null) {
// Only restore state if there's no deep link
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 null;
}

return (
<NavigationContainer
initialState={initialState}
onStateChange={(state) =>
AsyncStorage.setItem(PERSISTENCE_KEY, JSON.stringify(state))
}
>
{/* ... */}
</NavigationContainer>
);
}

开发模式

¥Development Mode

此功能在开发模式下特别有用。你可以使用以下方法有选择地启用它:

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

const [isReady, setIsReady] = React.useState(__DEV__ ? false : true);

虽然它也可以用于生产,但请谨慎使用,因为如果应用在特定屏幕上崩溃,它可能会导致应用无法使用 - 因为重新启动后用户仍将在同一屏幕上。

¥While it can be used for production as well, use it with caution as it can make the app unusable if the app is crashing on a particular screen - as the user will still be on the same screen after restarting.

加载视图

¥Loading View

由于状态是异步恢复的,因此应用必须在获得初始状态之前呈现一个空/正在加载视图一段时间。为了解决这个问题,我们可以在 isReadyfalse 时返回一个加载视图:

¥Because the state is restored asynchronously, the app must render an empty/loading view for a moment before we have the initial state. To handle this, we can return a loading view when isReady is false:

if (!isReady) {
return <ActivityIndicator />;
}

警告:可串行化状态

¥Warning: Serializable State

每个参数、路由和导航状态都必须完全可序列化,此功能才能发挥作用。通常,你会将状态序列化为 JSON 字符串。这意味着你的路由和参数不得包含任何函数、类实例或递归数据结构。如果 React Navigation 遇到不可序列化的数据,它已经是 在开发过程中警告你,所以如果你打算保留导航状态,请注意警告。

¥Each param, route, and navigation state must be fully serializable for this feature to work. Typically, you would serialize the state as a JSON string. This means that your routes and params must contain no functions, class instances, or recursive data structures. React Navigation already warns you during development if it encounters non-serializable data, so watch out for the warning if you plan to persist navigation state.

你可以在将初始状态对象传递到容器之前对其进行修改,但请注意,如果你的 initialState 不是 有效的导航状态,React Navigation 可能无法正常处理这种情况。

¥You can modify the initial state object before passing it to container, but note that if your initialState isn't a valid navigation state, React Navigation may not be able to handle the situation gracefully.