React遍历对象坐标获取地址时所有对象地址相同如何解决?
问题根因
- 状态更新逻辑错误:每次地址请求成功后直接将
cityName赋值为仅包含当前地址的数组,之前的请求结果会被完全覆盖,最终数组内仅保留最后一次请求返回的地址,导致所有条目渲染结果一致。 - 异步请求时序不可控:多个并行发送的地理编码请求返回顺序和遍历
workouts的顺序不一定匹配,就算改为追加数组也会出现地址和对应对象不匹配的问题。 - 渲染逻辑错误:遍历所有运动对象时直接输出整个
cityName数组的字符串内容,没有和单个对象做关联匹配。
解决方案
将地址状态改为存储「运动对象ID: 对应地址」的映射结构,渲染时根据当前对象的ID提取对应地址,即可解决覆盖、匹配错误的问题。
修改后完整代码:
export const WorkoutsData = [ { id: 1, coords: { latitude: 56.27360151291927, longitude:-82.84886256490017 }, }, { id: 2, coords: { latitude: 49.27360151291927, longitude: -75.84886256490017 }, }, { id: 3, coords: { latitude: 39.27360151291927, longitude: -79.84886256490017 }, } ];
import React, { useEffect, useState } from "react"; import "./styles.css"; import { WorkoutsData } from "./WorkoutLocation"; const App = () => { const [workouts, setWorkouts] = useState(WorkoutsData); // 状态改为存储ID和地址的映射关系 const [cityNameMap, setCityNameMap] = useState({}); const id = (Date.now() + "").slice(-10); useEffect(() => { workouts.forEach((workout) => { // 已存在对应地址则跳过重复请求 if (cityNameMap[workout.id]) return; fetch( `https://geocode.xyz/${workout.coords.latitude},${workout.coords.longitude}?geoit=json` ) .then((res) => res.json()) .then((result) => { const address = `${result.staddress}, ${result.city}`; // 函数式更新,基于之前的状态追加新地址映射,不会覆盖旧数据 setCityNameMap(prev => ({ ...prev, [workout.id]: address })); }); }); }, [workouts, cityNameMap]); return ( <> <div key={id}> {workouts.map((workout) => { // 根据当前对象ID取对应地址,未返回结果时显示加载提示 const address = cityNameMap[workout.id] || "地址加载中..."; return <h2 key={workout.id}>{address}</h2>; })} </div> </> ); }; export default App;
内容的提问来源于stack exchange,提问作者prakash subba
相关产品推荐
相关产品推荐

