如何在React的state对象数组中插入新对象实现多城市天气数据渲染
问题原因与修正方案
核心错误点
- 初始
datastate定义为数组类型,但两次setData都传入单个对象,直接覆盖了数组结构 - React state更新要求不可变操作,往数组中追加数据需要基于原数组生成新数组,不能直接修改原数组
优化实现方案
推荐用Promise.all并行发起多个城市的天气请求,一次性更新state,相比链式请求效率更高:
import React, { useEffect, useState } from "react"; import axios from "axios"; import { Container, Card, ListGroup } from "react-bootstrap"; // 记得替换成你自己的openweathermap appkey const KEY = "你的appid"; // 要查询的城市列表,后续新增城市直接修改这个数组即可 const CITIES = ["Ohio", "California"]; const WeatherPanel = () => { const [data, setData] = useState([]); const fetchData = async () => { try { // 并行发起所有城市的天气请求 const requestList = CITIES.map(city => axios.get(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${KEY}`) ); const resList = await Promise.all(requestList); // 格式化所有返回结果,生成符合要求的对象数组更新state const formattedList = resList.map(res => ({ description: res.data.weather[0].description, icon: res.data.weather[0].icon, temp: res.data.main.temp, city: res.data.name, })); setData(formattedList); } catch (err) { console.log(err); } }; useEffect(() => { fetchData(); }, []); return ( <div> <Container fluid> <Card style={{ width: "50%", boxShadow: "0 0 10px 2px lightgrey" }}> <Card.Header> Favorite Location</Card.Header> <ListGroup variant="flush"> {/* 遍历state数组渲染每个城市的天气信息 */} {data.map(item => ( <ListGroup.Item key={item.city}> <img src={`http://openweathermap.org/img/wn/${item.icon}@2x.png`} alt={item.description} /> {item.city}:{item.temp},{item.description} </ListGroup.Item> ))} </ListGroup> </Card> </Container> </div> ); }; export default WeatherPanel;
保留原链式调用写法的修改方案
如果不想调整原有请求逻辑,只需要修改setData的写法即可:
// 第一次请求成功后用函数式更新追加新对象 setData(prev => [...prev, { description: res.data.weather[0].description, icon: res.data.weather[0].icon, temp: res.data.main.temp, city: res.data.name, }]); // 第二次请求成功后同样用函数式更新,基于上一次的state追加新项 setData(prev => [...prev, { description: res.data.weather[0].description, icon: res.data.weather[0].icon, temp: res.data.main.temp, city: res.data.name, }]);
说明:setData传入函数的参数prev是更新前的最新state,用扩展运算符...prev把原数组的项展开,再追加新对象,就生成了全新的数组完成不可变更新
内容的提问来源于stack exchange,提问作者zer0day
相关产品推荐
相关产品推荐

