useEffect中useState更新值未生效,打印坐标为undefined求助
React Native Expo-Location 获取坐标后打印 undefined 的问题修复
问题核心原因
- useState 更新是异步的:你在调用
setLatitude和setLongitude后立刻打印对应的 state,此时 state 还未完成更新,因此输出 undefined。 - 权限请求与位置获取逻辑脱节:权限请求在异步函数中执行,但后续获取位置的代码未等待权限请求完成就运行,可能导致权限未通过时就尝试获取位置。
- 不必要依赖 web geolocation polyfill:既然已经使用
expo-location,直接调用它提供的 API 更稳定,无需额外安装 polyfill 再使用navigator.geolocation。
修正后的完整代码
import { StatusBar } from 'expo-status-bar'; import { useState, useEffect } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps'; import * as Location from 'expo-location'; export default function App() { const [locationCoords, setLocationCoords] = useState({ latitude: null, longitude: null }); const [errorMsg, setErrorMsg] = useState(null); useEffect(() => { const getCurrentLocation = async () => { // 请求位置权限 const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { setErrorMsg('Permission to access location was denied'); return; } // 使用 expo-location 获取当前位置 try { const location = await Location.getCurrentPositionAsync({ accuracy: Location.Accuracy.High // 根据需求调整精度 }); const { latitude, longitude } = location.coords; // 更新坐标 state setLocationCoords({ latitude, longitude }); // 直接打印获取到的原始坐标(此处能拿到最新值) console.log("latitude: ", latitude); console.log("longitude: ", longitude); } catch (err) { setErrorMsg(`Failed to get location: ${err.message}`); } }; getCurrentLocation(); }, []); // 监听坐标 state 变化,打印更新后的状态 useEffect(() => { if (locationCoords.latitude && locationCoords.longitude) { console.log("Updated location state: ", locationCoords); } }, [locationCoords]); return ( <View style={styles.container}> {errorMsg && <Text style={styles.errorText}>{errorMsg}</Text>} {locationCoords.latitude && locationCoords.longitude ? ( <MapView style={styles.map} provider={PROVIDER_GOOGLE} initialRegion={{ latitude: locationCoords.latitude, longitude: locationCoords.longitude, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} > <Marker coordinate={{ latitude: locationCoords.latitude, longitude: locationCoords.longitude }} title="Current Location" /> </MapView> ) : ( <Text>Loading location...</Text> )} <StatusBar style="auto" /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, map: { width: '100%', height: '100%', }, errorText: { color: 'red', marginBottom: 10, }, });
关键修复说明
- 合并坐标 state:将 latitude 和 longitude 整合为一个对象 state,便于统一管理和更新。
- 整合权限与位置逻辑:把权限请求和位置获取放在同一个异步函数中,确保权限通过后才执行位置获取操作。
- 使用 expo-location 原生 API:用
Location.getCurrentPositionAsync替代navigator.geolocation,更适配 Expo 环境,无需额外 polyfill。 - 正确打印坐标:在获取位置后直接打印返回的原始坐标值,同时通过额外的 useEffect 监听 state 变化,打印更新后的状态。
- 增加异常捕获:处理位置获取时可能出现的错误,避免应用崩溃。
- 完善 UI 反馈:根据 state 状态展示加载提示、错误信息或地图组件,提升用户体验。
内容的提问来源于stack exchange,提问作者tomtom
相关产品推荐
相关产品推荐

