React.memo vs useMemo 区别
一句话总结:React.memo 是缓存「整个组件」,useMemo 是缓存「组件内的计算值/函数」,一个管组件,一个管数据,用途完全不同。
1. 核心定义与本质#
🧩 React.memo#
- 类型:高阶组件 (HOC)
- 作用:缓存组件本身,防止组件不必要的重新渲染
- 使用场景:给函数组件做性能优化,避免父组件渲染时子组件无脑跟着重渲染
- 缓存目标:组件的渲染结果(UI)
🧮 useMemo#
- 类型:React Hook
- 作用:缓存「昂贵计算的结果」,避免每次渲染都重复计算
- 使用场景:组件内耗时的计算逻辑、需要稳定引用的对象/数组
- 缓存目标:变量/值
2. 语法对比#
React.memo(包裹整个组件)#
// 缓存整个子组件,props 不变就不重新渲染
const Child = React.memo(function Child({ name }) {
return <div>{name}</div>;
});jsxuseMemo(组件内使用,缓存值)#
function Parent() {
const [count, setCount] = useState(0);
// 缓存昂贵计算结果,依赖项不变就不重新计算
const expensiveValue = useMemo(() => {
console.log("只在依赖变化时执行");
return count * 2; // 模拟耗时计算
}, [count]); // 依赖数组
return <div>{expensiveValue}</div>;
}jsx3. 关键区别对照表#
| 特性 | React.memo | useMemo |
|---|---|---|
| 是什么 | 高阶组件 (HOC) | Hook |
| 缓存什么 | 整个组件的渲染结果 | 组件内的计算值/变量 |
| 解决什么问题 | 防止子组件不必要重渲染 | 防止组件内重复昂贵计算 |
| 使用位置 | 包裹函数组件 | 写在组件内部 |
| 依赖控制 | 自动浅比较 props | 手动传入依赖数组 |
| 返回值 | 一个缓存后的新组件 | 一个缓存后的计算值 |
4. 最直观的使用场景#
✅ 用 React.memo 的场景#
子组件是纯展示组件,props 不变就不需要重新渲染:
// 父组件渲染时,Child 只要 props 不变就不重渲染
const Parent = () => {
const [num, setNum] = useState(1);
return (
<>
<button onClick={() => setNum(num+1)}>加一</button>
{/* 子组件被 memo 缓存 */}
<Child name="小明" />
</>
);
};
// 包裹子组件
const Child = React.memo(({ name }) => {
console.log("子组件渲染"); // 只有 props 变才会打印
return <div>{name}</div>;
});jsx✅ 用 useMemo 的场景#
组件内有耗时计算,不想每次渲染都重新算:
const List = ({ data }) => {
// 过滤大量数据是耗时操作,用 useMemo 缓存结果
const filteredList = useMemo(() => {
return data.filter(item => item.value > 100);
}, [data]); // 仅 data 变化时重新过滤
return <div>{filteredList.map(item => <div key={item.id}>{item.name}</div>)}</div>;
};jsx5. 重要注意事项#
- 不要滥用:
- 简单组件、轻量计算,用它们反而增加性能开销(缓存本身有成本)
- 只给频繁重渲染的子组件用 React.memo
- 只给耗时计算用 useMemo
- 都是浅比较:
- React.memo 浅比较 props
- useMemo 浅比较依赖项
- 传递对象/数组时,需要配合 useMemo/useCallback 保证引用不变
- 本质不同:
- React.memo = 组件级缓存
- useMemo = 数值级缓存
总结#
- React.memo:给组件瘦身,防止子组件无效重渲染
- useMemo:给计算瘦身,防止重复执行昂贵逻辑
- 二者互补,不是二选一,可在项目中配合使用