React中如何避免浏览器坐标在异步API调用后才加载?
问题解决:React中获取浏览器坐标后调用天气API时参数undefined的问题
问题核心在于navigator.geolocation.getCurrentPosition是异步操作,你调用fetchBrowserCoordinates()后立刻执行API请求,此时coords状态还没被更新,自然会出现undefined,undefined的参数,导致400错误。下面提供两种可行的解决方式:
方案一:将坐标获取封装为Promise,等待获取完成再请求API
把坐标获取逻辑改成返回Promise的形式,这样就能用await等待坐标获取成功后再执行后续API请求:
const fetchBrowserCoordinates = () => { return new Promise((resolve, reject) => { if (!navigator.geolocation) { reject(new Error('GeoLocation is not supported by your browser.')); } else { navigator.geolocation.getCurrentPosition( (position) => { resolve(position.coords); }, () => { reject(new Error('Unable to retrieve your location.')); } ); } }); }; useEffect(() => { fetchRealTimeWeatherData(); }, []); const fetchRealTimeWeatherData = async () => { try { // 等待坐标获取完成 const coordsData = await fetchBrowserCoordinates(); setCoords(coordsData); const API_KEY = '____YOUR____API____KEY____'; const location = `${coordsData.latitude},${coordsData.longitude}`; // 统一用async/await写法,避免混合then和await const response = await fetch( `https://api.tomorrow.io/v4/weather/realtime?units=imperial&location=${location}&apikey=${API_KEY}`, options ); const weatherData = await response.json(); setWeather(weatherData); console.log(weatherData); // 直接打印获取到的数据,避免状态更新异步导致的旧值问题 } catch (err) { console.error(err); } };
方案二:利用React状态依赖,当坐标更新后自动触发API请求
通过监听coords状态的变化,当坐标成功获取并更新状态后,再执行天气API请求:
const fetchBrowserCoordinates = () => { if (!navigator.geolocation) { console.log('GeoLocation is not supported by your browser.'); } else { navigator.geolocation.getCurrentPosition((position) => { setCoords(position.coords); }, () => { console.log('Unable to retrieve your location.'); } ); } }; // 组件加载时先获取坐标 useEffect(() => { fetchBrowserCoordinates(); }, []); // 当coords更新且有效时,请求天气数据 useEffect(() => { if (coords?.latitude && coords?.longitude) { fetchRealTimeWeatherData(); } }, [coords]); const fetchRealTimeWeatherData = async () => { const API_KEY = '____YOUR____API____KEY____'; const location = `${coords.latitude},${coords.longitude}`; try { const response = await fetch( `https://api.tomorrow.io/v4/weather/realtime?units=imperial&location=${location}&apikey=${API_KEY}`, options ); const weatherData = await response.json(); setWeather(weatherData); console.log(weatherData); } catch (err) { console.error(err); } };
两种方案都能解决异步顺序问题,你可以根据自己的代码习惯选择。方案一更适合需要严格按顺序执行的场景,方案二更贴合React的状态驱动逻辑。
内容的提问来源于stack exchange,提问作者Mcloide
相关产品推荐
相关产品推荐

