Hooks使用useMemo,useCallback

useMemo 和 useCallback 是 React Hooks 中用于性能优化的重要工具,它们通过缓存计算结果或函数,避免不必要的重复计算和子组件渲染.

memo

React.memo 为高阶组件。它与 React.PureComponent 非常相似。默认只会props数据做浅层比较,如果需要控制对比过程我们可以将比较函数作为第二个参数传入:React.memo(MyComp, areEqual)深层比较,函数组件一般优化都是结合memo、useMemo、useCallback性能优化

useMemo:缓存计算结果

useMemo 用于优化组件的渲染性能。它会在依赖项变化时重新计算 memoized 值,并且只在依赖项变化时重新渲染组件。你应该在以下情况使用 useMemo:
1.昂贵的计算:如果你有一个复杂的计算,它应该只在某些依赖项变化时重新运行,那么 useMemo 非常有用。它会记住最后计算的值,并仅在依赖项变化时重新计算。

2避免不必要的渲染:如果你有一个组件,它在重新渲染时执行昂贵的 DOM 操作,那么你应该通过 useMemo 来优化它,使其只在依赖项变化时重新渲染。
3.依赖项变化时才重新计算值:如果你想基于 props 的某些值来计算一些数据,并且你只想在依赖 props 值变化时重新计算该数据。

//复杂计算
const memoizedValue = useMemo(() => {
  return computeExpensiveValue(data); // 仅在 data 变化时重新计算
}, [data]); // 依赖项数组

//避免对象/数组重新创建
const config = useMemo(() => ({
  mode: 'dark',
  timeout: 1000,
}), []); // 空依赖项表示仅初始化一次

useCallback:缓存函数 

缓存函数本身,避免函数因父组件重渲染而重新创建,导致子组件不必要的更新。

  • 传递回调函数给子组件(搭配 React.memo 使用)

  • 依赖函数引用的副作用(如 useEffect 依赖函数)

  • 高频事件处理函数(如滚动、拖拽)

  • const memoizedCallback = useCallback(() => {
      doSomething(a, b); // 仅在 a 或 b 变化时重新创建函数
    }, [a, b]); // 依赖项数组
    
    useEffect(() => {
      fetchData();
    }, [fetchData]); // 依赖 useCallback 缓存的 fetchData
    const Child = React.memo(({ onClick }) => { /* ... */ });
    
    const Parent = () => {
      const handleClick = useCallback(() => {
        console.log('Clicked!');
      }, []); // 空依赖项表示函数永不变化
      return <Child onClick={handleClick} />;
    };

 注意事项

  1. 避免过度优化
    只在真正需要时使用(如性能瓶颈),滥用可能增加内存开销。

  2. 正确处理依赖项
    依赖项缺失会导致缓存数据过期(Stale Closure 问题)

  3. 与 React.memo 配合

// 仅当 props 变化时重渲染
const Child = React.memo(({ data, onClick }) => { /* ... */ });

    4.避免缓存简单计算:   

// ❌ 不必要的 useMemo
const sum = useMemo(() => a + b, [a, b]);
// ✅ 直接计算即可
const sum = a + b;

常见误区

//用 useMemo 代替 useEffect
// ❌ 错误:useMemo 用于副作用
useMemo(() => {
  fetchData(); // 副作用不应放在 useMemo
}, [data]);

// ✅ 正确:使用 useEffect
useEffect(() => {
  fetchData();
}, [data]);

//忽略依赖项导致缓存失效

const [count, setCount] = useState(0);
const increment = useCallback(() => {
  setCount(count + 1); // ❌ 闭包陷阱:count 始终为初始值
}, []); // 缺少 count 依赖

// ✅ 正确写法:依赖项包含 count
const increment = useCallback(() => {
  setCount(c => c + 1); // 或使用函数式更新
}, []);

总结

  1. 按需缓存:仅在性能敏感场景使用(如大数据处理、高频交互)。

  2. 配合 React.memo:避免子组件因父组件无关状态更新而重渲染。

  3. 优先用函数式更新:解决闭包陷阱(如 setCount(c => c + 1))。

合理使用 useMemo 和 useCallback 可以显著提升 React 应用性能,但需结合具体场景权衡利弊

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值