React中useState处理对象数组时DOM不渲染数据的问题求助
React天气应用数据无法渲染问题修复
问题描述
开发React天气小应用时,通过latLongStore循环调用axios获取多城市天气数据,请求正常但weatherData数组内容无法在DOM中显示——数组长度正确但无内容渲染。
代码片段
... const latLongStore = [ { latitude: 23.8315, longitude: 91.2868, title: "Agartala", color: "#299617", code: 'VEAT' }, { latitude: 23.0225, longitude: 72.5714, title: "Ahmedabad", color: "#299617", code: 'VCBI' }, ... ] const initialData = { city: '', latitude: 0, longitude: 0, max_temperature: 0, min_temperature: 0 } function TableView(props) { const [weatherData, updateWeatherData] = useState([initialData]); useEffect(() => { latLongStore.forEach((latLong) => { axios.get(`api-url`).then((response) => { const fetchedData = { city: latLong.title, latitude: response.data.latitude, longitude: response.data.longitude, max_temperature: response.data.daily.temperature_2m_max[0], min_temperature: response.data.daily.temperature_2m_min[0] } console.log(fetchedData); updateWeatherData(weatherData => [...weatherData, fetchedData]); }) }) }, []); switch (weatherData.length) { default: return ( <div> <br /> <br /> <br /> <br /> LOADING... {weatherData.length} </div> ) // weatherData contains 62 objects after fetch but no values show up in DOM case 62: return ( <div> <br /> <br /> <br /> <br /> { weatherData.forEach((data) => { <div> { data.city } : { data.latitude }, { data.longitude } </div> }) } </div> ) // default: // return ( // <div> // <br /> // <br /> // <br /> // <br /> // LOADING... // </div> // ) } } export default TableView;
输出现象
- 加载过程中:显示
LOADING...和数组长度递增 - 数组长度达到62后:仅显示空白,无城市数据内容
修复方案
1. 替换forEach为map实现列表渲染
JSX中渲染列表必须使用map,因为forEach仅执行遍历操作无返回值,无法生成React可识别的元素数组。map会返回每个元素对应的JSX节点,同时要为列表元素添加唯一key属性(优先使用数据自身的唯一标识,比如城市code)。
修改case 62的渲染代码:
case 62: return ( <div> <br /> <br /> <br /> <br /> { weatherData.map((data) => ( <div key={data.code}> { data.city } : { data.latitude }, { data.longitude } </div> )) } </div> )
2. 优化请求与状态更新逻辑
当前循环调用updateWeatherData会触发多次组件重渲染,且初始状态包含无效空数据,建议用Promise.all批量处理请求,一次性更新状态,提升性能:
useEffect(() => { // 批量生成所有请求的Promise const fetchTasks = latLongStore.map(latLong => axios.get(`api-url`) .then(res => ({ city: latLong.title, latitude: res.data.latitude, longitude: res.data.longitude, max_temperature: res.data.daily.temperature_2m_max[0], min_temperature: res.data.daily.temperature_2m_min[0] })) ); // 等待所有请求完成后一次性更新状态 Promise.all(fetchTasks) .then(allData => updateWeatherData(allData)) .catch(err => console.error('天气数据请求失败:', err)); }, []);
同时将初始状态改为空数组,避免混入无效数据:
const [weatherData, updateWeatherData] = useState([]);
3. 简化加载判断逻辑
无需依赖固定长度62判断加载完成,直接根据数组是否为空判断,逻辑更健壮:
// 替换原switch逻辑 if (weatherData.length === 0) { return ( <div> <br /> <br /> <br /> <br /> LOADING... </div> ); } return ( <div> <br /> <br /> <br /> <br /> { weatherData.map((data) => ( <div key={data.code}> { data.city } : { data.latitude }, { data.longitude } </div> )) } </div> );
内容的提问来源于stack exchange,提问作者onapte
相关产品推荐
相关产品推荐

