为什么React中调用setState后首次渲染获取不到对应state值
问题核心原因
- 你只声明了一个全局的
cityName状态存储城市名,每次逆地理编码请求返回后都会覆盖这个状态的值,自然只会保留最后一次请求的结果 - 提交运动记录生成workout对象时,逆地理编码请求还没有返回结果,此时写入对象的
cityName还是空值或者上一次请求的旧值 - 每次
workouts数组更新后都会遍历所有项重复发起请求,会造成不必要的性能浪费,也会出现多次覆盖cityName的问题
解决方案
直接把城市名写入workouts数组中对应id的对象项,不要通过全局cityName状态中转,同时避免重复请求已有城市名的记录,修正后代码如下:
import React, { useEffect, useState } from 'react'; const RenderLocation = () => { const [workouts, setWorkouts] = useState([]); if (workoutType === 'running') { const runningData = { id, coords, workoutType, distance, duration, cadence, pace, cityName: '', // 初始化为空,后续请求后回填 }; setWorkouts((result) => [...result, runningData]); clearInputs(); } else if (workoutType === 'cycling') { const cyclingData = { id, coords, workoutType, distance, duration, elevation, speed, cityName: '', // 初始化为空,后续请求后回填 }; setWorkouts((result) => [...result, cyclingData]); clearInputs(); } useEffect(() => { // 只请求还没有cityName的记录,避免重复请求 const noCityWorkouts = workouts.filter(item => !item.cityName); noCityWorkouts.forEach((exercise) => { fetch( `https://geocode.xyz/${exercise.coords.latitude},${exercise.coords.longitude}?geoit=json` ) .then((res) => res.json()) .then((result) => { const locationStr = `${result.staddress}, ${result.city}`; // 只更新对应id的workout的cityName,不会影响其他记录 setWorkouts(prev => prev.map(item => item.id === exercise.id ? {...item, cityName: locationStr} : item )); }); }); }, [workouts]); return ( <> {workouts.map((workout) =>{ return( <h2 key={workout.id} className="workout-title"> {workout.cityName || '加载中...'} </h2> )})} </> ) }; export default RenderLocation;
内容的提问来源于stack exchange,提问作者prakash subba
相关产品推荐
相关产品推荐

