You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo Router返回时如何保留页面状态?避免重渲染

Expo Router 返回页面状态丢失的解决办法

Expo Router 默认采用类似 Web 的路由行为:跳转新页面时会卸载上一页组件,所以调用 router.back() 返回时,上一页会重新渲染,状态自然丢失。下面是几种比 Redux 更简便的解决方案,没必要切换到 React Navigation:

1. 用 useFocusEffect 控制副作用执行时机

如果只是不想让 useEffect 里的逻辑重复执行,或者需要在页面聚焦时更新状态,直接用 Expo Router 内置的 useFocusEffect(它基于 React Navigation 的同名 API):

import { useFocusEffect } from '@react-navigation/native';
import React from 'react';
import { Link } from 'expo-router';

export default function ScreenA() {
  useFocusEffect(
    React.useCallback(() => {
      // 只有页面首次加载,或者从其他页面返回聚焦时才会执行
      console.log('Screen A 已聚焦');
      return () => {
        // 页面失焦时的清理逻辑(可选)
      };
    }, [])
  );

  return <Link href="/screen-b">去 Screen B</Link>;
}

这个方法不用额外存状态,只是控制代码执行时机,适合简单场景。

2. 开启页面持久化布局

如果需要完整保留页面的所有状态(比如输入框内容、滚动位置),可以在根布局里配置持久化:

// app/_layout.js
import { Stack } from 'expo-router';

export default function RootLayout() {
  return (
    <Stack screenOptions={{
      // 开启滚动位置持久化
      persistScrollPosition: true,
      // 关闭页面失焦时的卸载逻辑,保留组件状态
      unmountOnBlur: false,
    }}>
      <Stack.Screen name="screen-a" />
      <Stack.Screen name="screen-b" />
    </Stack>
  );
}

设置 unmountOnBlur: false 后,页面切换时不会卸载上一页组件,状态自然保留。注意不要给太多页面开这个,避免内存占用过高。

3. 轻量跨页面状态方案(替代 Redux)

如果需要跨页面共享少量状态,用 React Context 或者本地存储就够了,比 Redux 简单太多:

React Context 示例

先创建一个状态上下文:

// app/contexts/PageState.js
import { createContext, useContext, useState } from 'react';

const PageStateContext = createContext();

export function PageStateProvider({ children }) {
  const [inputValue, setInputValue] = useState('');
  return (
    <PageStateContext.Provider value={{ inputValue, setInputValue }}>
      {children}
    </PageStateContext.Provider>
  );
}

export function usePageState() {
  return useContext(PageStateContext);
}

然后在根布局里包裹:

// app/_layout.js
import { Stack } from 'expo-router';
import { PageStateProvider } from './contexts/PageState';

export default function RootLayout() {
  return (
    <PageStateProvider>
      <Stack>
        <Stack.Screen name="screen-a" />
        <Stack.Screen name="screen-b" />
      </Stack>
    </PageStateProvider>
  );
}

最后在 ScreenA 里使用:

import { TextInput } from 'react-native';
import { Link } from 'expo-router';
import { usePageState } from '../contexts/PageState';

export default function ScreenA() {
  const { inputValue, setInputValue } = usePageState();

  return (
    <>
      <TextInput 
        value={inputValue} 
        onChangeText={setInputValue} 
        placeholder="输入内容"
      />
      <Link href="/screen-b">去 Screen B</Link>
    </>
  );
}

返回 ScreenA 时,输入框的内容就会保留。


内容的提问来源于stack exchange,提问作者Marcel Cohen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:01:21