前言

React.memo()是 React 的一个顶层 API 且为高阶组件,它对组件做的事类似于React.PureComponet,不同的是:React.memo()是对函数组件进行优化,React.PureComponent是定义类组件使用的;

React.Component、React.PureComponent

了解React.memo()之前,让我们先来了解一下React.ComponentReact.PureComponent这两个组件,只要理解了这两个组件React.memo()就能自然而然的 get 到了~

React.Component

这里引用 React 官方介绍:React.Component 是使用 ES6 classes 方式定义 React 组件的基类;
只要是写类组件就需要用到它;

1
2
3
4
5
class Name extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>
}
}

React.PureComponent

React.PureComponentReact.Component的区别是内部实现了shouldComponentUpdate(), 会对组件的 props 和 state 进行浅层比较,如果比较下来数据没有改变,组件则不会重复刷新;
举个例子:

先用 React.Component 写一个小 demo:

然后我们点击 Add 按钮,可以看到点击一次 dom 就会重新渲染一次:

然后再把 state 固定设置为 1,看看在数据相同的情况下,dom 是否会重新渲染:


很明显,上面的结果可以看出不管 setState 的值是否相同,dom 都会无差别的更新,项目一旦庞大起来性能就会存在很大的问题;为了解决这个问题,react 提供了 React.PureComponent;

下面让我们把 demo 小小的修改一下:

这个时候点击 Add 按钮,点击再多次,只要 setState 的值是一样的就只会触发一次更新,避免了性能的浪费;

使用 React.PureComponent主要注意的点:

  1. React.PureComponent 中的 shouldComponentUpdate() 仅作对象的浅层比较;
  2. 如果数据结构很复杂,可能会产生错误结果;

React.memo()

这里引用react官网的原文:

  1. 如果你的组件在相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现。这意味着在这种情况下,React 将跳过渲染组件的操作并直接复用最近一次渲染的结果。
  2. React.memo 仅检查 props 变更。如果函数组件被 React.memo 包裹,且其实现中拥有 useState,useReducer 或 useContext 的 Hook,当 context 发生变化时,它仍会重新渲染。
  3. 默认情况下其只会对复杂对象做浅层对比,如果你想要控制对比过程,那么请将自定义的比较函数通过第二个参数传入来实现。

以上对React.memo的讲解已经足够清晰了~

1
2
3
4
5
6
7
8
9
10
11
function MyComponent(props) {
/* 使用 props 渲染 */
}
function areEqual(prevProps, nextProps) {
/*
如果把 nextProps 传入 render 方法的返回结果与
将 prevProps 传入 render 方法的返回结果一致则返回 true,
否则返回 false
*/
}
export default React.memo(MyComponent, areEqual);

让我们再把上面点击按钮的小demo改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import React, { useState } from 'react'

const Test: React.FC<IObjectProps> = () => {
let [count, setCount] = useState(0)

const addHandle = (): void => {
// 这里固定设置count的值为1
setCount(1)
}

return (
<div style={{ padding: '10px' }}>
{console.log('dom 渲染')}
<p>{count}</p>
<button onClick={addHandle}>Add</button>
</div>
)
}

// 使用React.memo包裹组件
export default React.memo(Test)

这个时候只会在count的值由0变为1的时候触发 console.log('dom 渲染'), 当count值为1再去设置成1的时候,组件就不会再重复的刷新了~

总结

React.memo()减少函数组件的无用渲染,为React函数组件性能优化提供了一个有效的方法。