React类组件this.setState是否存在类似useState的eagerState优化?
React类组件this.setState是否存在与useState一致的相同值跳过重渲染优化?
核心结论
- 函数组件的
useState/useReducer内置了eager state急算优化+Object.is值相等校验逻辑:如果更新传入的新状态和当前状态比对结果为相等,React会直接跳过该组件及对应子组件的重渲染,不会进入render执行流程。 - 类组件的
this.setState默认不存在同等级别的值比较跳过渲染优化,这也是实际测试时连续执行this.setState({count: 1})会重复触发渲染的根本原因。
类组件setState的默认更新逻辑
普通类组件如果继承自React.Component,调用setState时的默认处理规则非常直接:
- 只要触发了
setState调用,React默认就会将当前组件标记为待重渲染,不会主动对传入的state对象做深度或浅度的值比对。 - 测试代码中写的
this.setState({count: 1}),每次调用都会生成一个全新的对象字面量,在JS逻辑里{count: 1} === {count: 1}的返回值本身就是false,React默认不会深入对象内部比对属性值,自然会每次都触发重渲染。
类组件实现相同值跳过重渲染的方案
如果需要类组件在状态无实际变化时跳过不必要的重渲染,可以通过两种官方支持的方式实现:
- 方案1:继承
React.PureComponent代替React.Component。PureComponent内置了props与state的浅比较逻辑,当新旧props、新旧state的第一层属性经浅比对全部相等时,会自动跳过本次render执行。要注意浅比较不会递归比对嵌套对象的属性,复杂嵌套状态场景下可能出现更新漏判。 - 方案2:手动实现
shouldComponentUpdate生命周期钩子,自定义新旧props、state的比对规则,当返回值为false时React会直接跳过本次组件重渲染。
代码示例
import React, { PureComponent } from 'react'; class OptimizedCounter extends PureComponent { state = { count: 1 } handleClick = () => { // 连续点击触发setState,因为count值和当前状态一致,浅比较判定无变化,不会触发重渲染 this.setState({ count: 1 }) } render() { console.log('组件执行render'); return <button onClick={this.handleClick}>测试重复setState</button> } }
注意:即使用了
PureComponent,如果你的state更新存在嵌套对象属性变化,浅比较无法识别深层属性的变动,可能导致视图不更新,这种场景建议要么做状态扁平化处理,要么在shouldComponentUpdate中实现针对性的比对逻辑。
内容的提问来源于stack exchange,提问作者lingxi
相关产品推荐
相关产品推荐

