memo
一、认识
React.memo
为高阶组件,跟 React.PureComponent
作用一样。但是 React.memo
仅检测 props
的变化。
二、背景
在日常开发中,有很多React 父组件引用React 子组件的场景,React 父组件 状态的更新,会触发React 子组件重新渲染,无论父组件是否有传值给子组件。如下所示:
import React from "react";
import ReactDOM from "react-dom";
function ParentComponent() {
let [number, setNumber] = React.useState(0);
const handleClick = (e) => {
setNumber(number + 1);
};
console.log("父组件");
return (
<div>
<p>{number}</p>
<button onClick={handleClick}>增加</button>
<ChildrenComponent />
</div>
);
}
function ChildrenComponent() {
console.log("子组件");
return <div></div>;
}
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
现象: 每次点击按钮,父组件状态发生变化,子组件都没有接收父组件的任何状态,但是子组件也还是触发更新了。这样对于性能是很不好的
解决: 我们希望的情形是: React 父组件 某一个状态更新,只有接收这个状态的子组件会触发更新渲染,如果没有接收这个状态,则不会触发更新渲染。
三、语法
React.memo(Component,compare)
-
Component: 原始组件本身
-
compare: 一个函数,用于判断是否执行更新。如果没有
compare
,将浅比较props
为diff
规则,如果相等,当前fiber
完成工作,停止向下调和节点,所以被包裹的组件即将不更新-
语法
React.memo(Component,(prev,next)=>{
return prev.attr !== next.attr
})
-
四、用法
4.1 类组件
import React from "react";
import ReactDOM from "react-dom";
class ParentComponent extends React.Component {
state = { number: 0 };
handleClick = (e) => {
this.setState({ number: this.state.number + 1 });
};
render() {
console.log("父组件");
return (
<div>
<p>{this.state.number}</p>
<button onClick={this.handleClick}>增加</button>
<ChildrenComponent />
</div>
);
}
}
class ChildrenComponent extends React.Component {
render() {
console.log("子组件");
return <div></div>;
}
}
ChildrenComponent = React.memo(ChildrenComponent);
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
现象: 通过React.memo
装饰子组件,子组件不会随着父组件与之无关的状态的变化而触发更新渲染了。
4.2 函数组件
import React from "react";
import ReactDOM from "react-dom";
function ParentComponent() {
let [number, setNumber] = React.useState(0);
const handleClick = (e) => {
setNumber(number + 1);
};
console.log("父组件");
return (
<div>
<p>{number}</p>
<button onClick={handleClick}>增加</button>
<ChildrenComponent />
</div>
);
}
function ChildrenComponent() {
console.log("子组件");
return <div></div>;
}
ChildrenComponent = React.memo(ChildrenComponent);
ReactDOM.render(<ParentComponent />, document.getElementById("root"));
现象: 通过React.memo
装饰子组件,子组件不会随着父组件与之无关的状态的变化而触发更新渲染了。