为何useEffect循环中两种setImages写法的输出存在差异?
React循环中状态更新两种写法的差异解析
第一段代码逻辑
useEffect(() => { console.log("useeffect"); let image = []; for (let i = 0; i < 5; i++) { image = [...image, "https://source.unsplash.com/random"]; } setImages(image); }, []);
对应输出:
这段代码是先在本地拼好完整数组后再更新状态:
- 循环5次的过程中,每次都是把同一个固定的链接字符串加到数组里。因为循环是同步执行的,这个
random链接不会在循环过程中生成新的随机地址,所以最终数组里是5个完全一样的链接。 - 最后一次性把这个数组传给
setImages,组件更新后自然会渲染5张一模一样的图片(毕竟链接相同,Unsplash返回的是同一张随机图)。
第二段代码逻辑
useEffect(() => { for (let i = 0; i < 5; i++) { setImages((images) => [...images, "https://source.unsplash.com/random"]); } }, []);
对应输出:
这段代码的差异核心在两个地方:
- 函数式更新的特性:每次调用
setImages时传入的是回调函数,React会保证这个回调能拿到当前最新的状态值。循环5次,每次都基于当前的images数组追加新元素,最终状态会从空数组变成包含5个元素的数组。 - 随机链接的生成时机:每次执行
setImages的回调时,都会重新生成random链接——也就是说每一次循环都会触发Unsplash生成一个新的随机图片地址,所以最终数组里的5个链接全不一样,渲染出来就是5张不同的图片。
另外补充:React在同步代码块中会批量处理状态更新,所以这5次setImages不会触发5次组件重渲染,而是合并成一次,但这对最终的状态结果没有影响,因为函数式更新始终依赖最新状态,最终还是能得到5个元素的数组。
内容的提问来源于stack exchange,提问作者Mohit Yadav
相关产品推荐
相关产品推荐

