在React Native中结合React Navigation使用useContext遇错求助
修复Context错误并实现trackList持久化
一、解决TypeError: Cannot read property '_context' of undefined错误
问题根源
App.js中Stack.Navigator外层被多余的大括号包裹,导致React无法正确解析组件结构,破坏了Context的作用域传递逻辑。
修复步骤
修改App.js的返回部分,移除Stack.Navigator外层的冗余大括号:
// 修改后的App.js完整代码 import { createStackNavigator } from "@react-navigation/stack"; import Home from "./Screens/Home"; import Host from "./Screens/Host"; import Join from "./Screens/Join"; import { NavigationContainer } from "@react-navigation/native"; import React, { useState, createContext } from "react"; const Stack = createStackNavigator(); export const HostContext = createContext(null) export default function App() { const [trackList, setTrackList] = useState([]); return ( <HostContext.Provider value={{trackList, setTrackList}}> <NavigationContainer> <Stack.Navigator initialRouteName="Home" screenOptions={{ gestureEnabled: false }} > <Stack.Screen name="Home" component={Home} /> <Stack.Screen name="Host" component={Host} /> <Stack.Screen name="Join" component={Join} /> </Stack.Navigator> </NavigationContainer> </HostContext.Provider> ); }
二、修复Host.js的闭包陷阱问题
Host.js中useEffect的依赖数组为空,导致回调内捕获的trackList始终是初始空数组,更新时会丢失历史数据。改用函数式更新规避闭包问题:
// 修改后的Host.js useEffect部分 useEffect(() => { setTrackListener(roomID, (t) => { if (t != null) { console.log(t.name); // 通过函数式更新获取最新状态,避免闭包陷阱 setTrackList(prevList => [...prevList, t.name]); } }) }, [roomID]); // 添加roomID到依赖数组,确保监听逻辑仅在roomID变化时重新执行
三、实现trackList持久化(关闭页面不重置)
使用@react-native-async-storage/async-storage将数据保存到本地存储,确保页面重启后数据不丢失:
1. 安装依赖
npm install @react-native-async-storage/async-storage # 或使用yarn yarn add @react-native-async-storage/async-storage
2. 升级App.js,添加持久化逻辑
import { createStackNavigator } from "@react-navigation/stack"; import Home from "./Screens/Home"; import Host from "./Screens/Host"; import Join from "./Screens/Join"; import { NavigationContainer } from "@react-navigation/native"; import React, { useState, createContext, useEffect } from "react"; import AsyncStorage from '@react-native-async-storage/async-storage'; // 导入AsyncStorage const Stack = createStackNavigator(); export const HostContext = createContext(null) export default function App() { const [trackList, setTrackList] = useState([]); // 组件挂载时加载本地存储的trackList useEffect(() => { const loadSavedTracks = async () => { const savedData = await AsyncStorage.getItem('trackList'); if (savedData) { setTrackList(JSON.parse(savedData)); } }; loadSavedTracks(); }, []); // trackList更新时自动保存到本地存储 useEffect(() => { const saveTracks = async () => { await AsyncStorage.setItem('trackList', JSON.stringify(trackList)); }; saveTracks(); }, [trackList]); return ( <HostContext.Provider value={{trackList, setTrackList}}> <NavigationContainer> <Stack.Navigator initialRouteName="Home" screenOptions={{ gestureEnabled: false }} > <Stack.Screen name="Home" component={Home} /> <Stack.Screen name="Host" component={Host} /> <Stack.Screen name="Join" component={Join} /> </Stack.Navigator> </NavigationContainer> </HostContext.Provider> ); }
完成以上修改后,既可以解决Context传递错误,又能保证关闭页面重新打开后trackList的数据不会丢失。
内容的提问来源于stack exchange,提问作者Adrian Russo
相关产品推荐
相关产品推荐

