You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
  },
});

关键修复说明

  1. 合并坐标 state:将 latitude 和 longitude 整合为一个对象 state,便于统一管理和更新。
  2. 整合权限与位置逻辑:把权限请求和位置获取放在同一个异步函数中,确保权限通过后才执行位置获取操作。
  3. 使用 expo-location 原生 API:用Location.getCurrentPositionAsync替代navigator.geolocation,更适配 Expo 环境,无需额外 polyfill。
  4. 正确打印坐标:在获取位置后直接打印返回的原始坐标值,同时通过额外的 useEffect 监听 state 变化,打印更新后的状态。
  5. 增加异常捕获:处理位置获取时可能出现的错误,避免应用崩溃。
  6. 完善 UI 反馈:根据 state 状态展示加载提示、错误信息或地图组件,提升用户体验。

内容的提问来源于stack exchange,提问作者tomtom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:32:19