React render渲染的state与真实state不一致:修改数组属性后视图未同步
问题原因
- 你在
changeArr函数执行初始就深拷贝了初始状态的arr,整个循环过程中修改的都是同一个localArr对象引用,每次调用setArr传入的都是相同内存地址的对象,React做状态浅比较时会判定状态未发生变更,因此不会触发重渲染,页面内容自然不会实时更新。 - 异步更新过程中始终基于初始的数组副本修改,没有获取最新的状态值,也会导致更新结果不符合预期。
修复代码
优化更新逻辑,每次更新时使用函数式更新获取最新状态,同时每次都生成新的数组引用触发重渲染:
import { useEffect, useState } from 'react'; const App = (p: any) => { console.log('render!!'); const [arr, setArr] = useState([ { loading: true }, { loading: true }, { loading: true }, { loading: true } ]); useEffect(() => { changeArr(); }, []); const changeArr = async () => { for (let i = 0; i < 4; i++) { await new Promise(res => setTimeout(res, 1000)); // 函数式更新拿到最新状态,用map生成新数组,仅修改对应下标的属性 setArr(prevArr => prevArr.map((item, index) => index === i ? { ...item, loading: false } : item )); } }; return ( <> <div>{JSON.stringify(arr)}</div> </> ); }; export default App;
注意要点
- 不要在异步函数执行初期就拷贝状态值,异步闭包里保存的始终是初始的状态快照,无法拿到更新后的最新状态。
- React状态更新依赖引用变化,修改数组/对象类型的状态时必须返回全新的引用才能触发重渲染。
内容的提问来源于stack exchange,提问作者SleepDevil
相关产品推荐
相关产品推荐

