跳到主要内容

memo

2024年01月10日
柏拉文
越努力,越幸运

一、认识


React.memo() 允许你的组件在 props 没有改变的情况下跳过重新渲染。

二、语法


import { memo } from 'react';

const MemoizedComponent = memo(SomeComponent, arePropsEqual?)
  • SomeComponent: 要进行记忆化的组件。memo 不会修改该组件,而是返回一个新的、记忆化的组件。它接受任何有效的 React 组件,包括函数组件和 forwardRef 组件。

  • arePropsEqual: 一个函数,接受两个参数:组件的前一个 props 和新的 props。如果旧的和新的 props 相等,即组件使用新的 props 渲染的输出和表现与旧的 props 完全相同,则它应该返回 true。否则返回 false。通常情况下,你不需要指定此函数。默认情况下,React 将使用 Object.is 比较每个 prop

  • MemoizedComponent: memo 返回一个新的 React 组件。它的行为与提供给 memo 的组件相同,只是当它的父组件重新渲染时 React 不会总是重新渲染它,除非它的 props 发生了变化。

三、用法


3.1 默认比较函数

默认情况下,React 将使用 Object.is 比较每个 prop

import { memo } from 'react';

function MyComponent(){
return <div>My Component</div>
}

const MemoizedComponent = memo(MyComponent)

3.2 自定义比较函数

如果指定了自定的比较函数, React 将使用自定义比较函数比较每个 prop。如果自定义比较函数返回 true, 该组件将不会重新渲染。

import { memo } from 'react';

function MyComponent(){
return <div>My Component</div>
}

const MemoizedComponent = memo(MyComponent, (oldProps, newProps)=>{
return oldProps === newProps;
})

四、场景


4.1 精准渲染

未使用 memo 缓存之前: Appnum 的变化导致 App 组件重新渲染。造成的现象就是, Component1 组件与 App 中的 num 状态毫无关系, 但是却因为 num 的变化而重新渲染了, 造成渲染浪费。

function Component1(props){
const { num } = props;
console.log("Component1 Render", num);

return <div> Component 1 组件</div>
}

function App(){
const [num,setNum] = useState(0);
console.log("App Render");

const handleClick = ()=>{
setNum(num + 1);
}

return <div>
<h3 onClick={ handleClick }>App 组件</h3>
<Component1 { num: 0 } />
</div>
}

使用 memo 缓存之后: Appnum 的变化导致 App 组件重新渲染, Component1 组件使用 memo 包裹, 内部通过 Object.is 对比前后 num 的值有无变化, 由于 num 始终为 0, 所以 Component1 组件不会重新渲染。

function Component1(props){
const { num } = props;
console.log("Component1 Render", num);

return <div> Component 1 组件</div>
}

const MemoComponent1 = memo(Component1);

function App(){
const [num,setNum] = useState(0);
console.log("App Render");

const handleClick = ()=>{
setNum(num + 1);
}

return <div>
<h3 onClick={ handleClick }>App 组件</h3>
<MemoComponent1 { num: 0 } />
</div>
}