React-SCU、PureComponent、memo
react 性能优化 前端
比如有以下代码:
import React, { Component } from "react";
import Banner from "./Banner";
import Home from "./Home";
export class ComponentPerformance extends Component {
constructor(props) {
super(props);
this.state = {
name: "Niko",
};
}
changeName() {
this.setState((state) => {
return {
name: state.name,
};
});
}
render() {
console.log("App render");
const { name } = this.state;
return (
<div>
<h2>{name}</h2>
<button
onClick={(e) => {
this.changeName();
}}
>
改名字
</button>
<Home></Home>
<Banner></Banner>
</div>
);
}
}
export default ComponentPerformance;
当我们调用 setState 修改 state 中的值的时候,会触发 render,此时 Home 和 Banner 组件也会触发各自的 render,但是此时子组件并不依赖父组件的值,所以这次 render 是没有必要的,会对性能造成一定影响。
shouldComponentUpdate(SCU)
React 提供了一个生命周期 shouldComponentUpdate,该方法有两个参数
- nextProps 修改后最新的 props 属性
- nextState 修改后最新的 state 属性
该方法返回值是一个 boolean
- 返回 true,则需要调用 render,默认是 true
- 返回 false,不需要调用 render
可以通过在该方法内判断 nextProps/nextState 中的值是否与 this.props/this.state 中的值相同,来返回 true/false 控制 render 的执行,提高性能。
PureComponent
当然实际开发中,如果这么写的话,需要判断太多字段了,所以 React 提供了一个 PureComponent,类组件只需要继承自PureComponent,就可以达到上面的效果。
PureComponent实际是对新旧 state 和新旧 props 做了一次浅层比较,即
return !shallowEqual(state, nextState) || !shallowEqual(props, nextProps);
返回 true 时就会 re-render。
PureComponent的原型上会有一个标识,在通过继承自它的类创建的实例上,通过原型链也会找到这个标识,通过这个标识判断是否这样去判断。如果自身实现了 SCU 方法,会先判断SCU方法的返回值。
memo
PureComponent是在类组件中使用的,如果是函数组件,就需要使用 memo 了。
import React, { memo } from "react";
const Footer = memo((props) => {
console.log("Footer render");
return <div>{props.name}</div>;
});
export default Footer;
就是因为内部是使用浅层比较做的判断是否需要re-render, 所以在 setState 的时候,对于对象类型,不要直接修改其值然后 setState,这样在判断的时候由于内存地址相同而不会触发更新。