如何使用useState存储并合并多个API返回的标题数据?
问题解决:批量API请求后合并数据到useState数组
问题根源
你的代码存在两个核心问题:
- 状态覆盖:每次调用
setDataLoc(dataLoc.title)时,直接用单个标题字符串替换了原本的数组状态,没有做累加操作。 - 异步并发冲突:多个
fetch请求是异步执行的,React的useState更新基于状态快照,多个并发更新会互相覆盖,最终只保留最后一次请求的结果。
解决方案一:函数式状态更新(逐个累加)
使用useState的函数式更新语法,每次基于上一次的状态数组添加新标题,避免覆盖:
const [dataLoc, setDataLoc] = useState([]); const ids = [1,2,3,4,5,6,7,8,9,10]; useEffect(() => { // 用forEach替代map,因为不需要返回值 ids?.forEach((id) => { fetch(`https://jsonplaceholder.typicode.com/posts/${id}`) .then((response) => response.json()) .then((data) => { // 函数式更新,基于旧状态生成新数组 setDataLoc(prevState => [...prevState, data.title]); }) .catch((error) => console.error(error)); }); }, []); console.log(dataLoc);
解决方案二:Promise.all批量请求(推荐)
通过Promise.all等待所有API请求完成后,一次性更新状态,减少状态更新次数,性能更优:
const [dataLoc, setDataLoc] = useState([]); const ids = [1,2,3,4,5,6,7,8,9,10]; useEffect(() => { // 生成所有请求的Promise数组,提前提取标题 const fetchTasks = ids.map(id => fetch(`https://jsonplaceholder.typicode.com/posts/${id}`) .then(res => res.json()) .then(data => data.title) .catch(err => { console.error(`请求ID ${id} 失败:`, err); return null; // 出错时返回null,不中断整体请求 }) ); // 等待所有请求完成后统一更新状态 Promise.all(fetchTasks) .then(allTitles => { // 过滤掉请求失败的null值 const validTitles = allTitles.filter(title => title !== null); setDataLoc(validTitles); }) .catch(globalErr => console.error("批量请求失败:", globalErr)); }, []); console.log(dataLoc);
说明
- 方案一适合需要实时展示每个请求结果的场景,但会触发多次状态更新。
- 方案二更高效,仅触发一次状态更新,适合需要所有数据加载完成后再展示的场景。
内容的提问来源于stack exchange,提问作者Botol Shuvo
相关产品推荐
相关产品推荐

