React 的 useMemo
钩子详解
useMemo
是 React 提供的一个性能优化 Hook,用于缓存计算结果,避免在每次渲染时都进行重复计算。
基本语法
javascript
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
- 第一个参数:计算函数,返回需要缓存的值
- 第二个参数:依赖项数组,当依赖项变化时才会重新计算
核心机制
-
缓存触发条件:
- 使用
Object.is
逐个比较依赖项 - 任一依赖项变化 → 重新计算并缓存新值
- 所有依赖项不变 → 直接返回缓存值
- 使用
-
缓存存储方式:
- 存储在组件对应的 Fiber 节点
- 组件卸载时缓存销毁
- 空依赖数组
[]
→ 永久缓存
主要应用场景
1. 高性能计算优化
javascript
const filteredList = useMemo(() =>
hugeList.filter(item => item.value > threshold),
[threshold, hugeList]);
2. 稳定引用类型
javascript
const config = useMemo(() => ({ color: theme, size: "large" }), [theme]);
3. 避免子组件不必要渲染
javascript
const MemoizedComponent = React.memo(Child);
function Parent() {
const memoizedProps = useMemo(() => ({ onClick: handleClick }), []);
return <MemoizedComponent {...memoizedProps} />;
}
与相关 Hook 的区别
特性 | useMemo |
useEffect |
useCallback |
---|---|---|---|
执行时机 | 渲染阶段同步执行 | 浏览器绘制后异步执行 | 渲染阶段同步执行 |
主要用途 | 缓存计算结果 | 处理副作用 | 缓存函数引用 |
返回值 | 返回缓存值 | 无返回值 | 返回缓存函数 |
依赖数组作用 | 控制缓存更新 | 控制副作用触发 | 控制函数更新 |
注意事项
- 不要过度使用:仅在计算开销大或需要稳定引用时使用
- 引用类型比较 :默认使用浅比较,对于复杂对象可结合
JSON.stringify
或 Lodash 的isEqual
实现深比较 - 组件内部使用 :
useMemo
仅适用于单个组件内部,跨组件共享需使用状态管理库 - 引用稳定性 :
useMemo
的真正价值在于保持数据引用的稳定性,而不仅是性能优化
代码示例
javascript
function ComplexCalculation({ data }) {
const result = useMemo(() => {
console.log('重新计算');
return data.reduce((acc, item) => acc + item.value, 0);
}, [data]);
return <div>总和: {result}</div>;
}
useMemo
是 React 性能优化的重要工具,但应合理使用,避免因过度优化导致代码复杂度增加。