memo
一、认识
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
缓存之前: App
中 num
的变化导致 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
缓存之后: App
中 num
的变化导致 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>
}