React Native中使用Context Hooks获取userLocation出现undefined错误求助
问题排查与解决方案
核心错误原因
你遇到的undefined is not an object(evaluating "usePlaceContext.userLocation")错误,本质是MapScreen组件没有被PlaceContext.Provider包裹:
- 你的ContextProvider仅在HomeScreen内部包裹了PlayGrounds组件,而MapScreen是独立的屏幕组件,不在Provider的子组件树中。当MapScreen调用
usePlaceContext()时,会返回undefined,解构userLocation自然会抛出错误。 - 另外,你在placeContext.jsx中额外引入了
MapView和Marker,这完全没必要——Context只负责数据传递,不需要导入UI组件。
具体修复步骤
1. 提升ContextProvider层级
将ContextProvider移到App的根组件(比如App.js),让所有需要使用PlaceContext的组件都处于Provider范围内:
// App.js示例 import { ContextProvider } from './context/placeContext'; import HomeScreen from './screens/HomeScreen'; import MapScreen from './screens/MapScreen'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; const Stack = createStackNavigator(); export default function App() { return ( <ContextProvider> <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Map" component={MapScreen} /> </Stack.Navigator> </NavigationContainer> </ContextProvider> ); }
同时移除HomeScreen里的ContextProvider:
// HomeScreen.jsx修改后 const HomeScreen = () => { return ( <ImageBackground source={backgroundImage} style={styles.container}> <PlayGrounds ListHeaderComponent={() => ( <SafeAreaView style={styles.frame}> <AppLogo /> <Search /> <View style={styles.locationContainer}> <Text style={styles.myLocation}>I here</Text> </View> </SafeAreaView> )} /> <StatusBar style="default" /> </ImageBackground> ); };
2. 修复placeContext里的代码问题
- 移除不必要的MapView导入
- 修复
userLocation中未定义的setErrorMsg:
// placeContext.jsx修改后 import { createContext, useContext, useState, useEffect } from "react"; import axios from "axios"; import * as Location from "expo-location"; const PlaceContext = createContext(); export const ContextProvider = ({ children }) => { const [places, setPlaces] = useState([]); const [filterPlaces, setFilterPlaces] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isError, setIsError] = useState(false); const [errorMsg, setErrorMsg] = useState(""); // 新增errorMsg状态 const [searchValue, setSearchValue] = useState(""); const [locality, setLocality] = useState({ latitude: 37.78825, longitude: 11.50078, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }); useEffect(() => { axios .post( "https://where2playdk.herokuapp.com/nearest?lat=55.70232019168349&lon=12.561693791177802" ) .then((response) => setPlaces(response.data)) .catch((error) => setIsError(true)) .finally(() => setIsLoading(false)); // 加载完成后设为false,逻辑更合理 }, []); const userLocation = async () => { let { status } = await Location.requestForegroundPermissionsAsync(); if (status !== "granted") { setErrorMsg("Permission denied"); // 现在setErrorMsg已定义 return; } try { let location = await Location.getCurrentPositionAsync({ enableHighAccuracy: true, }); setLocality({ latitude: location.coords.latitude, longitude: location.coords.longitude, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }); console.log(`my location: ${location.coords.latitude}, ${location.coords.longitude}`); } catch (err) { setErrorMsg("Failed to get location"); setIsError(true); } }; return ( <PlaceContext.Provider value={{ places, isLoading, isError, errorMsg, // 把errorMsg加入value,方便组件使用 setSearchValue, searchValue, locality, userLocation, }} > {children} </PlaceContext.Provider> ); }; export const usePlaceContext = () => useContext(PlaceContext);
验证修复
完成上述修改后,MapScreen就能正确获取到Context中的userLocation和locality,不会再出现undefined的错误。
内容的提问来源于stack exchange,提问作者saygas
相关产品推荐
相关产品推荐

