如何使用async/await获取Axios返回数据并在React-Leaflet组件中使用
问题核心原因
JSX的渲染逻辑是同步执行的,你在模板中直接调用async函数的写法不符合React渲染规则:async函数无论是否内部使用await,只要直接在渲染上下文执行,返回值都是Promise实例,React无法自动解析Promise的resolve结果作为渲染内容,因此你拿到的始终不是实际的经纬度数值。
除此之外你当前的代码还存在重复请求问题:同一个地址拆分两个函数分别请求纬度和经度,会发起两次完全相同的API请求,造成不必要的性能浪费。
修复方案
使用React的useState管理异步请求返回的经纬度数据,useEffect钩子执行异步请求逻辑,请求完成后更新状态触发组件重渲染,即可正常渲染坐标点。
完整修改代码如下:
import { useState, useEffect } from 'react' import { MapContainer, TileLayer, Marker, Popup, Circle } from 'react-leaflet'; import mockData from './testData/MOCK_DATA.json' import axios from 'axios'; import outageData from './testData/outageData.json' const fillBlueOptions = { fillColor: 'blue' }; // 合并经纬度请求,同一个地址只发起一次请求 async function getAddressCoordinates(location) { const resp = await axios.get(`https://api.geocodify.com/v2/geocode/json?api_key=替换为你自己的APIKEY&q=${location.outage_street}, ${location.outage_city}, Michigan, USA`); const [, lat, lng] = resp.data.response.bbox return { lat: Number(lat), lng: Number(lng) } } function OutageMap() { // 存储处理完经纬度的停电数据 const [processedOutages, setProcessedOutages] = useState([]) // 加载状态 const [loading, setLoading] = useState(true) // 组件挂载时批量请求所有地址的经纬度 useEffect(() => { const fetchAllCoordinates = async () => { try { const requestTasks = outageData.outages.map(async (outageItem) => { const coordinates = await getAddressCoordinates(outageItem) return { ...outageItem, ...coordinates } }) // 等待所有请求完成 const result = await Promise.all(requestTasks) setProcessedOutages(result) } catch (err) { console.error('坐标解析失败:', err) } finally { setLoading(false) } } fetchAllCoordinates() }, []) return ( <MapContainer center={[38.89, -77.059]} zoom={13} scrollWheelZoom={true}> <TileLayer attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> { loading ? ( <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', zIndex: 999 }}>坐标加载中...</div> ) : ( processedOutages.map(mock => ( <Circle key={mock.id /* 替换为你数据中的唯一标识字段 */} center={[mock.lat, mock.lng]} pathOptions={fillBlueOptions} radius={200} > <Popup>{mock.description}</Popup> </Circle> )) ) } </MapContainer> ); } export default OutageMap;
注意事项
- 请将代码中的APIKEY替换为你自己的geocodify接口密钥
- 若停电数据量较大,建议添加分批请求逻辑,避免短时间内请求量过大触发接口限流
- 可根据需求添加单条地址解析失败的兜底逻辑,避免某条数据请求失败导致全部数据渲染失败
内容的提问来源于stack exchange,提问作者Shafi Kamal
相关产品推荐
相关产品推荐

