跳到主要内容

shouldComponentUpdate

2024年03月06日
柏拉文
越努力,越幸运

一、认识


shouldComponentUpdate 当组件接收到新的 props 或调用 setState 更新 state 后,shouldComponentUpdate 会在渲染过程开始前被调用。根据返回值来决定是否需要渲染: 返回 true, 组件将继续更新, 调用 render 生成新的虚拟 DOM, 并最终提交到页面; 返回 false, 组件将跳过此次更新, render 不会被调用,组件保持当前状态和 UI 不变。这个方法应该是纯函数,即不能产生副作用,且只依据新旧 propsstate 做比较,返回一个布尔值。一般情况,不建议在该周期方法中进行深层比较,会影响效率, 同时也不能调用 setState,否则会导致无限循环调用更新。需要重点关注的是第二个参数 newState ,如果有 getDerivedStateFromProps 生命周期 ,它的返回值将合并到 newState ,供 shouldComponentUpdate 使用。

二、语法


shouldComponentUpdate(newProps,newState){
if(newProps.a !== this.props.a ){ /* props中a属性发生变化 渲染组件 */
return true
}else if(newState.b !== this.props.b ){ /* state 中b属性发生变化 渲染组件 */
return true
}else{ /* 否则组件不渲染 */
return false
}
}

三、场景


3.1 比较基础数据,控制渲染

比较基础数据,控制渲染: 可以直接比较前后数据是否相等

import React, { Component } from "react";
import ReactDOM from "react-dom";

class App extends Component {
constructor(props) {
super(props);
this.state = {
num: 0,
};
}
handleClick() {
this.setState({
num: this.state.num + 1,
});
}

shouldComponentUpdate(newProps, newState) {
if (newState.num !== this.state.num) {
return true;
}
return false;
}

render() {
const { num } = this.state;
return (
<div>
<h3>App 组件</h3>
{num}
<button onClick={() => this.handleClick()}>改变</button>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));

3.2 比较引用数据,控制渲染

比较引用数据,控制渲染: 不可以直接比较是否相等,需要借助 immutable.js 来对比

import React, { Component } from "react";
import ReactDOM from "react-dom";
import Immutable from "immutable";

class App extends Component {
constructor(props) {
super(props);
this.state = {
like: Immutable.Map({ a: 1, b: 2, c: 3 }),
};
}
handleClick() {
this.setState({
like: Immutable.Map({ a: 2, b: 2, c: 3 }),
});
}

shouldComponentUpdate(newProps, newState) {
if (Immutable.is(newState.like,this.state.like)) {
console.log('kk')
return true;
}
return false;
}

render() {
const { like } = this.state;
return (
<div>
<h3>App 组件</h3>
{like.get('a')}
<button onClick={() => this.handleClick()}>改变</button>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById("root"));