如何在React Navigation中实现页面缓存?解决StackNavigator重复加载问题
问题核心
StackNavigator 默认会在页面被弹出栈时卸载组件,导致再次进入时重新加载。要实现特定页面首次加载后缓存,可通过以下几种方式解决:
方案1:使用 BottomTabNavigator(适合底部标签切换场景)
如果你的页面是通过底部标签切换的结构,BottomTabNavigator 本身默认会缓存所有标签页组件,切换时不会重新挂载,完全符合你的需求。
示例结构:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import { NavigationContainer } from "@react-navigation/native"; import Home from '@/screens/Home'; import Profile from '@/screens/Profile'; import Test from "@/screens/Test"; import Login from "@/screens/Login"; const Tab = createBottomTabNavigator(); const Stack = createNativeStackNavigator(); function TabNavigator() { return ( <Tab.Navigator> <Tab.Screen name="Home" component={Home} /> <Tab.Screen name="Profile" component={Profile} /> </Tab.Navigator> ); } export default function Router({ children }) { return ( <NavigationContainer> <Stack.Navigator initialRouteName="TabNavigator" screenOptions={{ animation: "none", headerShown: false }} > <Stack.Screen name="TabNavigator" component={TabNavigator} /> <Stack.Screen name="Login" component={Login} /> <Stack.Screen name="Test" component={Test} /> </Stack.Navigator> {children} </NavigationContainer> ); }
方案2:StackNavigator 中启用 keepMounted 选项(React Navigation 6+)
如果必须使用纯 Stack 结构,可通过给特定页面设置 keepMounted: true,让页面即使不在栈顶也保持挂载状态,不会被卸载。
修改你的代码,在需要缓存的页面配置中添加该选项:
const screenList = [ { name: "Home", component: Home, options: { gestureEnabled: false, keepMounted: true, // 开启页面缓存 }, }, { name: "Profile", component: Profile, options: { gestureEnabled: false, keepMounted: true, // 开启页面缓存 }, }, { name: "Test", component: Test, options: { gestureEnabled: false, }, }, { name: "Login", component: Login, options: { gestureEnabled: false, }, }, ];
注意:该选项会增加内存占用,只给确实需要缓存的页面开启即可。
方案3:自定义组件缓存容器(灵活控制)
如果需要更精细的缓存控制,可自行实现一个缓存容器,通过 React 状态保存已加载的组件实例:
import React, { useState, useEffect } from 'react'; import { NavigationContainer } from "@react-navigation/native"; import { createNativeStackNavigator } from "@react-navigation/native-stack"; import Home from "@/screens/Home"; import Profile from "@/screens/Profile"; import Test from "@/screens/Test"; import Login from "@/screens/Login"; // 自定义缓存容器组件 function CachedScreen({ component: Component, ...props }) { const [isLoaded, setIsLoaded] = useState(false); const [cachedInstance, setCachedInstance] = useState(null); useEffect(() => { if (!isLoaded) { setCachedInstance(<Component {...props} />); setIsLoaded(true); } }, [isLoaded, Component, props]); return cachedInstance; } const Stack = createNativeStackNavigator(); export default function Router({ children }) { const screenList = [ { name: "Home", component: (props) => <CachedScreen component={Home} {...props} />, options: { gestureEnabled: false }, }, { name: "Profile", component: (props) => <CachedScreen component={Profile} {...props} />, options: { gestureEnabled: false }, }, { name: "Test", component: Test, options: { gestureEnabled: false }, }, { name: "Login", component: Login, options: { gestureEnabled: false }, }, ]; return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home" screenOptions={{ animation: "none", headerShown: false }} > {screenList.map((item, index) => { return ( <Stack.Screen key={index} name={item.name} component={item.component} options={item.options} /> ); })} </Stack.Navigator> {children} </NavigationContainer> ); }
内容的提问来源于stack exchange,提问作者秋水岂泛涟漪
相关产品推荐
相关产品推荐

