React Native中Context._context未定义错误(用户上下文包裹导航器)
解决
undefined is not an object (evaluating 'Context._context') 错误 这个问题的核心原因很明确:你在App组件的顶层调用了useContext(UserContext),但此时这个组件还没有被UserProvider包裹。UserProvider是在你的return语句的条件分支里,所以组件初始化的时候,Context完全没有被提供,自然会抛出这个错误。
具体问题拆解:
- 你的
App组件首先执行const { isSignedIn, check_and_set_signin_status } = useContext(UserContext);,这时候UserProvider还没渲染,UserContext没有被注入任何值,导致读取_context时出错。 - 另外你的
non_user_stack函数没有return语句,会默认返回undefined,这也会导致渲染问题。
修复步骤:
1. 把UserProvider移到App组件的最外层
确保整个App都处于Context的作用域内,这样任何内部组件都能正确访问Context的值。
2. 在App组件内添加useEffect初始化登录状态
调用check_and_set_signin_status来初始化isSignedIn的值,避免初始状态为null导致的渲染问题。
3. 修复non_user_stack的return问题
这个函数必须返回Stack.Navigator组件,否则无法渲染。
修改后的完整代码:
App.js
import React, { useContext, useEffect } from "react"; import { View, Text, AsyncStorage, Button } from "react-native"; import { createStackNavigator } from "@react-navigation/stack"; import HomeScreen from "./src/screens/HomeScreen"; import LoginScreen from "./src/screens/login"; import CalendarScreen from "./src/screens/Calendar"; import SignUpScreen from "./src/screens/signUp"; import { scale, vs } from "react-native-size-matters"; import { createDrawerNavigator } from "@react-navigation/drawer"; import { createMaterialBottomTabNavigator } from "@react-navigation/material-bottom-tabs"; import { Icon } from "react-native-elements"; import UserContext, { UserProvider } from "./src/screens/Context/UserContext"; import { NavigationContainer } from "@react-navigation/native"; const Tab = createMaterialBottomTabNavigator(); const Stack = createStackNavigator(); const Drawer = createDrawerNavigator(); const drawer_style = { backgroundColor: "#202B35", activeTintColor: "#000", width: 200, }; const drawer_item_style = { activeTintColor: "orange", inactiveTintColor: "#fff", itemStyle: { marginVertical: vs(10) }, }; // 修复return问题 const non_user_stack = () => { return ( <Stack.Navigator> <Stack.Screen name="Sign in - Cal " component={LoginScreen} options={({ navigation }) => ({ headerShown: true, headerTintColor: "orange", headerStyle: { backgroundColor: "#202B35", }, })} /> <Stack.Screen name="Sign up - Cal " component={SignUpScreen} options={({ navigation }) => ({ headerShown: true, headerTintColor: "orange", headerStyle: { backgroundColor: "#202B35", }, })} /> </Stack.Navigator> ); }; const UserMenu = () => { return ( <Drawer.Navigator initialRouteName="Home" drawerStyle={drawer_style} drawerContentOptions={drawer_item_style} drawerType="front" > <Drawer.Screen name="Home" component={MyStack} /> </Drawer.Navigator> ); }; const MyStack = () => { return( <Stack.Navigator> <Stack.Screen name="Cal" component={BottomNav} options={({ navigation }) => ({ headerShown: true, headerTintColor: "orange", headerStyle: { backgroundColor: "#202B35", }, headerLeft: (props) => ( <Icon size={25} name={"ios-menu"} iconStyle={{ fontSize: scale(30), color: "orange", margin: 5, marginLeft: 10, }} type="ionicon" color="orange" onPress={() => { navigation.toggleDrawer(); }} /> ), })} /> </Stack.Navigator> ) }; // 注意:BottomNav组件你没提供,确保它已正确定义 const AppContent = () => { const { isSignedIn, check_and_set_signin_status } = useContext(UserContext); // 初始化登录状态 useEffect(() => { check_and_set_signin_status(); }, []); // 处理isSignedIn为null的加载状态 if (isSignedIn === null) { return <View><Text>Loading...</Text></View>; } return ( <NavigationContainer> {isSignedIn === "false" ? <non_user_stack /> : <UserMenu />} </NavigationContainer> ); }; export default App = () => { return ( <UserProvider> <AppContent /> </UserProvider> ); };
UserContext.js(补充自动初始化逻辑)
import React, { useState, useEffect } from "react"; import * as Permissions from "expo-permissions"; import axios from "axios"; import { AsyncStorage } from "react-native"; import Constants from "expo-constants"; const UserContext = React.createContext(); const IS_SIGNEDIN = "is_signed_in"; export const UserProvider = ({ children }) => { const [isSignedIn, setSignIn] = useState(null); const [didAuthenticate, setAuthenticated] = useState(null); const check_and_set_signin_status = async () => { const signed_in = await AsyncStorage.getItem(IS_SIGNEDIN); if (signed_in == null || signed_in == "false") { await AsyncStorage.setItem(IS_SIGNEDIN, "false"); setSignIn("false"); } else { setSignIn("true"); } }; // 组件挂载时自动初始化登录状态 useEffect(() => { check_and_set_signin_status(); }, []); return ( <UserContext.Provider value={{ isSignedIn, check_and_set_signin_status, }} > {children} </UserContext.Provider> ); }; export default UserContext;
关键修复点总结:
- 将
UserProvider提升到App组件的外层,确保所有需要访问Context的组件都在其作用域内。 - 拆分出
AppContent组件,在其中使用useContext,此时它已经被UserProvider包裹。 - 修复
non_user_stack的return问题,确保它返回有效的导航器组件。 - 添加加载状态处理,避免
isSignedIn为null时的异常渲染。
内容的提问来源于stack exchange,提问作者0xD1x0n
相关产品推荐
相关产品推荐

