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

React中如何确保获取经纬度后再调用天气API?

解决React中获取地理位置后再请求天气的时序问题

问题根源

你代码里的核心问题是navigator.geolocation.getCurrentPosition是基于回调的异步API,不是Promise,所以await对它无效——代码会直接跳到axios请求那一步,此时lat和long还是初始的0值,自然请求到错误位置的天气。另外,即使你等了,setLat/setLong是异步更新状态的,刚调用完就去读lat/long也拿不到新值。

解决方案

把getCurrentPosition包装成Promise,这样就能用await正确等待位置获取完成,并且直接用回调里的坐标值发起请求,不用依赖状态(避免状态更新的异步延迟)。同时,不要把JSX存在状态里,应该存图标相关的标识,渲染时再生成JSX。

修改后的完整代码

import React from 'react';
import { useState, useEffect } from 'react';
import './css/weather.css'
import axios from 'axios';

const Weather = () => {
  const [temp, setTemp] = useState(0);
  const [wind, setWind] = useState('');
  const [windDir, setWindDir] = useState('');
  const [gust, setGust] = useState('');
  const [precip, setPrecip] = useState(0);
  const [iconType, setIconType] = useState(''); // 存day/night
  const [picName, setPicName] = useState(''); // 存图标文件名
  const [city, setCity] = useState('');
  const [loading, setLoading] = useState(true); // 加个加载状态更友好
  const [error, setError] = useState('');

  // 把getCurrentPosition包装成Promise
  const getCurrentPosition = () => {
    return new Promise((resolve, reject) => {
      navigator.geolocation.getCurrentPosition(resolve, reject);
    });
  };

  const getWeather = async () => {
    try {
      setLoading(true);
      // 等待位置获取完成
      const position = await getCurrentPosition();
      const { latitude, longitude } = position.coords;
      
      // 直接用获取到的坐标发起请求
      const response = await axios.get(`http://api.weatherapi.com/v1/current.json?key=6e6263afb84f44279f731543222510&q=${latitude},${longitude}&aqi=no`);
      const data = response.data;

      setCity(data.location.name);
      setTemp(data.current.temp_f);
      setWind(data.current.wind_mph);
      setWindDir(data.current.wind_dir);
      setGust(data.current.gust_mph);
      setPrecip(data.current.precip_in);
      
      const iconUrl = data.current.condition.icon;
      setPicName(iconUrl.slice(-7));
      setIconType(iconUrl.includes('day') ? 'day' : 'night');
    } catch (err) {
      setError('获取位置或天气失败,请检查权限或网络');
      console.error(err);
    } finally {
      setLoading(false);
    }
  };

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

  if (loading) return <div className='weather-container'>加载中...</div>;
  if (error) return <div className='weather-container'>{error}</div>;

  return (
    <div className='weather-container'>
      <p>
        <img src={`/assets/weather/64x64/${iconType}/${picName}`} alt="天气图标" />
      </p>
      <h2>{city}</h2>
      <p>{`Current Temp: ${Math.round(temp)} °F`}</p>
      <p>{`Wind: ${windDir} ${Math.round(wind)} mph Gusts: ${Math.round(gust)} mph`}</p>
      <p>{`Precip: ${Math.round(precip)}in`}</p>
    </div>
  );
};

export default Weather;

关键修改点

  • 封装getCurrentPosition为Promise,让await能正确等待位置获取
  • 直接使用回调返回的latitude和longitude发起请求,跳过状态更新的异步延迟
  • 将icon状态拆分为iconType和picName,不再存JSX,而是在渲染时生成,符合React状态管理最佳实践
  • 添加了加载和错误状态,提升用户体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:10:16