当前位置: 首页 > news >正文

useMemo和useCallback

1.useMemo缓存计算结果,缓存函数

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • 参数​​:接受一个函数(返回需要缓存的值)和一个依赖数组(依赖项变化时重新计算)。

  • ​返回值​​:返回函数计算的值,依赖未变化时直接复用缓存。

核心场景:

  • ​昂贵计算​​:对大量数据排序、过滤、复杂数学运算等,避免每次渲染都重新计算。

    const sortedList = useMemo(() => { 
    return bigData.sort((a, b) => a.value - b.value); // 大数据排序}, [bigData]);

  • ​引用稳定性​​:当需要将一个对象/数组作为 props 传递给子组件(且子组件用 React.memo优化时),避免因每次渲染生成新引用导致子组件无效更新。

    const config = useMemo(() => ({ timeout: 1000, retry: 3 }), []); 
    // 配置对象保持引用不变

    2.useCallback缓存函数

  • const memoizedCallback = useCallback(() => doSomething(a, b), [a, b]);
  • 参数​​:接受一个函数(需要缓存的函数)和一个依赖数组(依赖项变化时重新创建函数)。

  • ​返回值​​:返回缓存的函数实例,依赖未变化时复用之前的函数。

​核心场景​​:
  • ​子组件优化​​:当函数作为 props 传递给子组件(尤其是用 React.memo包裹的子组件)时,避免因函数引用变化导致子组件不必要的重新渲染。

  • const handleClick = useCallback(() => {console.log('Button clicked', count);
    }, [count]); // 依赖 count,count 变化时才更新函数return <MemoizedChild onClick={handleClick} />; // MemoizedChild 用 React.memo 包裹

    ​避免闭包陷阱​​:在定时器、事件监听等异步场景中,确保函数引用稳定,避免捕获到过期的状态。

    useEffect(() => {const timer = setInterval(() => {console.log('Current value:', stableValue); // 使用稳定的函数引用}, 1000);return () => clearInterval(timer);
    }, [stableValue]);

  • 区别

3. ​​依赖管理复杂​

2. ​​合理使用 React.memo 配合​

  • 如果你需要 ​​缓存一个计算结果​​(比如过滤后的列表、格式化后的数据),用 useMemo

  • 如果你需要 ​​缓存一个函数​​(比如传递给子组件的回调),用 useCallback

  • ​本质上,useCallback 是 useMemo 的一种特例​​(当缓存的函数返回值是函数本身时,两者可互换,但语义更清晰)。

  • 三、滥用 useMemo/useCallback 的问题

    1. ​​性能反而下降​

  • ​额外开销​​:useMemo和 useCallback本身需要维护缓存逻辑,​​首次渲染时会有额外的计算/创建成本​​,且依赖项变化时需要对比依赖数组。如果缓存的值或函数本身计算成本很低(比如简单的加法、返回常量),使用它们反而会增加不必要的复杂度。

  • // ❌ 滥用:计算简单,无优化必要 
    const doubled = useMemo(() => num * 2, [num]); // num * 2 是简单计算,直接写 num * 2 更清晰 
    const handleClick = useCallback(() => { setCount(count + 1); // 简单函数,无子组件依赖,直接定义即可 }, [count]);

  • 2. ​​代码可读性降低​

  • ​过度优化​​:滥用会导致代码中充斥大量 useMemo/useCallback,增加维护成本和理解成本。

  • ​掩盖真正问题​​:过度依赖缓存可能掩盖组件设计不合理(如子组件未合理拆分、状态管理混乱)的本质问题。

  • ​依赖数组错误​​:如果依赖项遗漏或错误(比如漏掉某个依赖),会导致缓存失效(useMemo重新计算,useCallback重新创建函数),引发 bug。而错误的依赖管理比直接重新计算/创建函数的代价更高。

    // ❌ 错误示例:漏掉依赖 count,导致函数内使用过期的 
    count const handleClick = useCallback(() => { 
    console.log(count); // 若 count 是依赖但未声明,这里可能拿到旧值 }
    , []); // 漏了 [count]
    

    四、最佳实践建议

    1. ​​优先考虑代码可读性与维护性​

  • ​默认不使用​​:大多数情况下,直接写普通函数或计算逻辑更清晰,除非有明确的性能瓶颈或引用稳定性需求。

  • ​按需使用​​:仅在以下场景使用:

    • 子组件用 React.memo优化,且需要稳定函数引用(用 useCallback)。

    • 计算逻辑复杂且依赖项变化频繁(用 useMemo)。

    • 需要避免闭包陷阱(如定时器、事件监听中的函数)。

  • ​子组件优化​​:如果子组件是纯展示组件(props 变化才重新渲染),用 React.memo包裹,再配合 useCallback缓存回调函数,才能真正减少渲染。

  • const Child = React.memo(({ onClick }) => {console.log('Child 渲染'); // 仅当 onClick 引用变化或 props 变化时渲染return <button onClick={onClick}>点击</button>;
    });function Parent() {const handleClick = useCallback(() => {console.log('点击事件');}, []); // 依赖为空,函数引用永远不变return <Child onClick={handleClick} />;
    }


文章转载自:

http://bcObwWIq.mzzqs.cn
http://DPFQhEdW.mzzqs.cn
http://l2MWfK1b.mzzqs.cn
http://9t5NtngW.mzzqs.cn
http://Q1UHJR53.mzzqs.cn
http://ZxhwsoJ8.mzzqs.cn
http://NzOZAbar.mzzqs.cn
http://xTYLEXjl.mzzqs.cn
http://KB5Itp27.mzzqs.cn
http://ZW0opRP0.mzzqs.cn
http://Ff4RbRQH.mzzqs.cn
http://qw5ibRo3.mzzqs.cn
http://DclTJYhI.mzzqs.cn
http://0D64KOEx.mzzqs.cn
http://KfJ6QdeS.mzzqs.cn
http://oeQ5SWHz.mzzqs.cn
http://kCD72dGW.mzzqs.cn
http://kwr33M3x.mzzqs.cn
http://CgHBXc1L.mzzqs.cn
http://EChFezBY.mzzqs.cn
http://NoUPOrCI.mzzqs.cn
http://RgY7zVhN.mzzqs.cn
http://hLaCZyxW.mzzqs.cn
http://H6QYPYW1.mzzqs.cn
http://QucnyFOd.mzzqs.cn
http://K8A6C0fI.mzzqs.cn
http://Jgsjj5FC.mzzqs.cn
http://OQT04SjZ.mzzqs.cn
http://e1QpzT3P.mzzqs.cn
http://4WDx9qL0.mzzqs.cn
http://www.dtcms.com/a/388576.html

相关文章:

  • 【数据结构---图的原理与最小生成树算法,单源最短路径算法】
  • 有发声生物(猫狗鸟等)与无发声生物(蚂蚁蝙蝠蛇等)的 “感知-->行动“
  • CC 攻击为什么越来越难防?
  • 量化交易 - Multiple Regression 多变量线性回归(机器学习)
  • 【机器学习】基于双向LSTM的IMDb情感分析
  • CLR-GAN训练自己的数据集
  • LeetCode 242 有效的字母异位词
  • 中州养老:Websocket实现报警通知
  • python+excel实现办公自动化学习
  • 深度学习快速复现平台AutoDL
  • 《股票智能查询与投资决策辅助应用项目方案》
  • nvm安装包分享【持续更新】
  • 2025年- H143-Lc344. 反转字符串(字符串)--Java版
  • 数据库的事务
  • Cadence SPB 2025安装教程(附安装包)Cadence SPB 24.1下载详细安装图文教程
  • .NET Framework 4.8 多线程编程
  • qt QHorizontalPercentBarSeries详解
  • 软考中级习题与解答——第七章_数据库系统(3)
  • Redis(基础数据类型/String)
  • python的面试题
  • 内聚和耦合基础
  • Java基本类型与包装类在MyBatis中的应用指南
  • 《Unity3D VR游戏手柄振动与物理碰撞同步失效问题深度解析》
  • 基于 Rust 的 CAD 工具demo示例
  • 多模态大模型研究每日简报【2025-09-17】
  • 2D平台动作游戏《Haneda Girl》推出免费体验版
  • 《艾尔登法环:黑夜君临》DLC泄露:更多角色和Boss!
  • 向量化执行引擎是啥?
  • LeetCode 刷题【81. 搜索旋转排序数组 II、82. 删除排序链表中的重复元素 II、83. 删除排序链表中的重复元素】
  • 关于二叉树的OJ练习