React 在 for 循环中 setState 最后一次执行结果会覆盖前面的结果

更新日期: 2024-09-28 阅读次数: 343 字数: 535 分类: ReactJS

使用场景

在实现一个批量查询的功能,前端使用 React 写了一个组件。

将多行输入分隔成多个搜索词,因为是模糊查询,搜索速度不快, 为了减少等待时间,于是每个搜索词逐一调用搜索接口。 然后,将搜索结果合并到一个数组,每返回一个结果,就立即显示。

有问题的代码

const [results, setResults] = useState<API.Item[]>([]);

for (const keyword of keywords) {
	// 每个搜索词逐一调用搜索接口
	let apiResult = await callSearchApi({keyword: keyword});
	setResults([...results, ...apiResult.data]);
}

这段代码的问题是,虽然从浏览器调试工具里看每个 API 请求都成功返回了。 也正确返回了数据。但是界面上只能显示出了最后一个搜索词的结果。 而不是批量查询的全部结果。

百思不得其解。

正确的写法

看了 React 官网 setState 文档,我也没有找到思路。于是网上搜索了一下,发现原来是 React 的刷新机制问题。

先说正确的写法是什么:

setResults(prevState => [...prevState, ...apiResult.data]);

然后界面展示就正常了。能看到所有查询结果了。

为什么呢?

因为 setState 触发的界面更新是异步的, 而为了提高性能,也不是每个 setState 都立即触发界面更新。 而会将短时间内的更新,做自动合并,然后只触发一次界面更新。

可以参考这里的说明:

https://mp.weixin.qq.com/s/hdxcESwminO_oE_Es81gCA

例如:

this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })

短时间内执行这三次,实际只会最后一次生效。且 count 不更新。

正确的写法是:

this,setState((prevState, props)=> {
	return {count: prevState.count + 1}
})
this,setState((prevState, props)=> {
	return {count: prevState.count + 1}
})
this,setState((prevState, props)=> {
	return {count: prevState.count + 1}
})

这样就能保证每个历史状态都能被更新。

狗屎,毫无意义的知识。

参考

  • https://www.cnblogs.com/ifnk/p/16739426.html
  • https://www.reddit.com/r/reactjs/comments/ouxq7z/update_state_from_a_foreach/

微信关注我哦 👍

大象工具微信公众号

我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊, 查看更多联系方式