跳到主要内容

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,将浅比较propsdiff规则,如果相等,当前 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装饰子组件,子组件不会随着父组件与之无关的状态的变化而触发更新渲染了。

原理