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

React天气应用开发:如何在调用API前获取用户地理位置数据

问题根源
  • 你的代码存在两处核心逻辑问题:
    1. navigator.geolocation.getCurrentPosition 是异步回调API,不会阻塞后续代码执行,现有逻辑在触发获取位置请求后立刻调用天气接口,此时userLat、userLon还保持初始值null,接口请求必然异常
    2. React的状态更新是异步批量执行的,就算你在位置获取的回调中执行了setUserLat,也无法在当前作用域立刻拿到最新的状态值
修复方案(async/await实现)

首先将地理位置获取逻辑封装为Promise,就可以通过await等待位置返回后再执行天气接口请求,逻辑完全符合你的预期:

import { useState, useEffect } from 'react';
import axios from 'axios';
import LocationOnIcon from '@mui/icons-material/LocationOn';
import GeoForecast from './GeoForecast'; // 按你的实际文件路径调整

const API_KEY = process.env.REACT_APP_WEATHER_API_KEY;

// 封装地理位置获取为Promise,适配async/await调用
const getUserPosition = () => {
  return new Promise((resolve, reject) => {
    if (!navigator.geolocation) {
      reject(new Error('Error: Geolocation is not supported by your browser'));
    }
    navigator.geolocation.getCurrentPosition(resolve, reject);
  });
};

export default function GeolocationForecast() {
  const [data, setData] = useState([]); // 天气数据为数组结构,初始值改为空数组更合理
  const [userLat, setUserLat] = useState(null);
  const [userLon, setUserLon] = useState(null);
  const [userStatus, setUserStatus] = useState(null);

  useEffect(() => {
    fetchUserGeolocationAndForecast();
  }, []);

  async function fetchUserGeolocationAndForecast() {
    try {
      setUserStatus('Loading...');
      // 等待地理位置获取成功
      const position = await getUserPosition();
      const { latitude, longitude } = position.coords;
      // 更新位置状态
      setUserLat(latitude);
      setUserLon(longitude);
      setUserStatus(null);
      // 用真实获取到的经纬度请求天气接口
      const apiUrl = `https://api.openweathermap.org/data/2.5/onecall?lat=${latitude}&lon=${longitude}&units=imperial&appid=${API_KEY}`;
      const res = await axios.get(apiUrl);
      setData(res.data.daily);
    } catch (err) {
      // 统一处理所有异常:不支持定位、用户拒绝授权、接口请求失败
      setUserStatus(err.message || 'Unable to retrieve your location or weather data');
      console.error(`Error: ${err}`);
    }
  }

  return (
    <div>
      <span><h1>7-Day Forecast</h1><LocationOnIcon fontSize="large" /></span>
      {userStatus && <h4>{userStatus}</h4>}
      <GeoForecast data={data} />
    </div>
  );
};
可选优化

如果后续你需要基于userLat、userLon的状态做更多拓展逻辑,也可以拆分为两个useEffect实现:第一个空依赖的useEffect只负责获取地理位置并更新状态,第二个useEffect监听userLat和userLon,当两个值都不为null时再触发天气接口请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 14:36:01