memo 是一个高阶组件 (HOC) ,用于优化整个组件的重新渲染。
作用
记忆组件的渲染结果。
优化性能:memo会对 props 进行浅比较,如果 props 没有变化,组件就不会重新渲染。如果父组件频繁重新渲染,而这个组件的 props 没有变化,使用``memo`` 可以避免不必要的重新渲染。
保持表单状态 :虽然表单form使用的是 useRef 而不是 useState,但如果使用 memo 可以避免组件被卸载和重新挂载,从而保持表单的状态。
注意:如果props有函数,且函数在父组件中没有用``useCallback`` 包裹,那么每次父组件渲染时,这些函数引用都会变化,导致``memo`` 失效。
举例
子组件
javascript
import { DynamicForm, DynamicFormRef, ConfirmDeleteDialog } from '@/components/dynamic-form';
import { memo, useRef } from 'react';
export const RpDialog = memo(
({
handleClick,
hidden = false,
visible = true,
hideModal,
}) => {
const formCallbackRef = useRef<DynamicFormRef>(null);
return (
<ConfirmDeleteDialog >
<DynamicForm
ref={formCallbackRef}
>
{/* {children} */}
</DynamicForm>
{/* {children} */}
</ConfirmDeleteDialog>
);
},
);
父组件
TypeScript
<section>
{rpDialogVisible && (
<RpDialog
hidden={true}
handleClick={handleClick}
visible={rpDialogVisible}
hideModal={hideRpDialogModal}
></RpDialog>
)}
</section>
如果不使用 memo :
- 每次父组件重新渲染时, RpDialog 都会重新渲染
- 即使对话框不可见( hidden={true} ),也会执行渲染逻辑
- 表单 ref 和回调函数会重新创建
使用 memo 后:
- 只有当 props( handleClick 、 hidden 、 visible 、 hideModal )真正变化时才重新渲染
- 父组件因搜索、筛选等操作重新渲染时, RpDialog 会被跳过
- 减少不必要的 DOM 操作和组件渲染
memo和useMemo区别
| 特性 | memo | useMemo |
|---|---|---|
| 类型 | memo是一个高阶组件HOC | useMemo是一个hook |
| 优化对象 | 优化整个组件的渲染 | 值级别的优化,函数的返回值 |
| 使用位置 | 组件定义外层 | 组件内部 |
| 作用 | 记忆组件的渲染结果 只有当 props 发生变化时才重新渲染 跳过父组件重新渲染时子组件的不必要渲染 | 缓存函数的返回值 只有依赖项变化时才重新计算 避免每次渲染都执行昂贵的计算 |
| 依赖检查 | props变化 | 数组变化 |