React天气应用开发:如何在调用API前获取用户地理位置数据
问题根源
- 你的代码存在两处核心逻辑问题:
navigator.geolocation.getCurrentPosition是异步回调API,不会阻塞后续代码执行,现有逻辑在触发获取位置请求后立刻调用天气接口,此时userLat、userLon还保持初始值null,接口请求必然异常- 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
相关产品推荐
相关产品推荐

