当useState对象值未变化时,如何阻止React组件重复渲染?
问题原因与解决方案
为什么会出现这种情况?
- 值没变化:你每次调用
setData({value:1})时,传入的新对象和当前data的value值完全一致,都是1,所以状态的实际内容没有任何改变。 - 组件仍重新渲染:React的
useState默认逻辑是,只要调用了setState方法,不管新值和旧值是否相等,都会触发组件重新渲染。而且因为你每次传的{value:1}是一个新的对象引用,React做引用比较时会认为状态“变了”,所以必然会触发渲染。
解决办法
方法一:函数式更新+判断值是否真的需要修改
在setData里用函数式更新,只有当新值和旧值不同时才返回新状态,否则返回旧状态,这样就能避免不必要的渲染:
const App = () => { console.log('APP re-render :>> ', Math.random()); const [data, setData] = useState({ value:1 }); const dataChange = () => { setData(prevData => { // 只有当值不同时才更新 if (prevData.value !== 1) { return { value:1 }; } // 返回旧状态,不会触发渲染 return prevData; }); } return ( <div> <button onClick={dataChange}>Click</button> <p>{data.value}</p> </div> ) }
方法二:结合React.memo做组件级优化
如果组件没有接收外部props,或者props变化时才需要渲染,可以用React.memo包裹组件,配合上面的判断逻辑,进一步优化:
const App = React.memo(() => { console.log('APP re-render :>> ', Math.random()); const [data, setData] = useState({ value:1 }); const dataChange = () => { setData(prevData => { if (prevData.value !== 1) { return { value:1 }; } return prevData; }); } return ( <div> <button onClick={dataChange}>Click</button> <p>{data.value}</p> </div> ) })
补充说明
React对对象类型的状态是做引用比较:哪怕两个对象内容完全一样,只要是不同的引用,React就会认为状态发生了变化。你每次传的{value:1}都是新创建的对象,所以默认会触发渲染;而如果返回旧的状态对象(同一个引用),React就会跳过渲染流程。
内容的提问来源于stack exchange,提问作者Pradeep
相关产品推荐
相关产品推荐

