使用场景
在实现一个批量查询的功能,前端使用 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 聊聊, 查看更多联系方式