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

React性能优化:useMemo vs useCallback

在React中,useMemouseCallback都是用于性能优化的Hook,核心作用是避免不必要的计算或重渲染,但它们的应用场景和作用对象不同。

一、基本用法与场景

1. useMemo:缓存计算结果

useMemo用于缓存计算密集型操作的结果,避免在每次渲染时重复执行昂贵的计算。

语法

const memoizedValue = useMemo(() => {// 复杂计算逻辑(如大量数据处理、循环计算等)return 计算结果;
}, [依赖数组]); // 当依赖项变化时,才重新计算

适用场景
当组件渲染时需要执行耗时的计算(如大数据过滤、排序、复杂公式计算等),且计算结果仅依赖特定变量时,用useMemo缓存结果,避免每次渲染都重复计算。

示例

function ProductList({ products, filterText }) {// 过滤商品列表(假设products数据量大,过滤逻辑复杂)const filteredProducts = useMemo(() => {return products.filter(product => product.name.includes(filterText));}, [products, filterText]); // 仅当products或filterText变化时,才重新过滤return (<ul>{filteredProducts.map(product => (<li key={product.id}>{product.name}</li>))}</ul>);
}
2. useCallback:缓存函数引用

useCallback用于缓存函数的引用,避免每次渲染时创建新的函数实例(即使函数逻辑没变)。

语法

const memoizedCallback = useCallback(() => {// 函数逻辑
}, [依赖数组]); // 当依赖项变化时,才创建新的函数引用

适用场景
当需要将函数作为props传递给子组件,且子组件通过React.memo(或PureComponent)优化时,用useCallback缓存函数引用,避免子组件因“函数引用变化”而触发不必要的重渲染。

示例

// 子组件(用React.memo优化,仅在props真正变化时重渲染)
const Child = React.memo(({ onHandleClick }) => {console.log("Child 渲染了");return <button onClick={onHandleClick}>点击</button>;
});// 父组件
function Parent() {const [count, setCount] = useState(0);// 用useCallback缓存函数引用:仅当count变化时,才会创建新函数const handleClick = useCallback(() => {console.log("点击了,当前count:", count);}, [count]); // 依赖countreturn (<div><p>count: {count}</p><button onClick={() => setCount(count + 1)}>1</button><Child onHandleClick={handleClick} /></div>);
}

如果不用useCallback,每次Parent渲染时会创建新的handleClick函数,Child会误以为props变化而重新渲染(即使React.memo优化也无效);用useCallback后,只有count变化时handleClick引用才变,Child才会重新渲染。

二、核心区别

维度useMemouseCallback
缓存对象计算结果(值)函数引用
作用避免重复执行昂贵计算避免子组件因函数引用变化重渲染
本质useMemo(fn, deps) 等价于 useCallback(fn, deps) 的返回值是 fn 本身,而 useMemo 的返回值是 fn() 的结果

三、滥用的后果

useMemouseCallback并非“越多越好”,滥用会导致负面影响:

  1. 增加内存开销
    缓存需要占用内存存储计算结果或函数引用,对于简单计算或不常变化的场景,缓存的内存成本可能超过优化收益。

  2. 逻辑错误(过时闭包)
    若依赖数组设置不当(如遗漏依赖),会导致缓存的结果/函数“过时”(引用旧的变量值),引发难以调试的bug。
    例:依赖数组遗漏变量,导致函数始终使用初始值:

    const [count, setCount] = useState(0);
    // 错误:依赖数组遗漏count,handleClick始终引用初始count(0)
    const handleClick = useCallback(() => {console.log(count); // 永远输出0
    }, []); 
    
  3. 代码复杂度提升
    过度使用会让代码冗余(额外的Hook调用和依赖管理),降低可读性和可维护性。实际上,大多数简单场景(如轻量计算、不传递给子组件的函数)不需要缓存。

  4. 抵消优化效果
    对于极简单的计算(如a + b),useMemo的缓存逻辑本身(判断依赖变化、读取缓存)可能比直接计算更耗时。

总结

  • useMemo:缓存计算结果,用于优化“昂贵计算”的重复执行。
  • useCallback:缓存函数引用,用于优化“子组件因函数props变化的重渲染”。
  • 原则:只在明确存在性能问题时使用(如频繁重渲染导致卡顿、计算耗时过长),避免过早优化和滥用。
http://www.dtcms.com/a/560861.html

相关文章:

  • Onsemi展示了垂直GaN-on-GaN半导体
  • 专业机票网站建设禅城区建设局网站
  • Java 日志演进:一文读懂主流框架
  • 第3章 变量与数据类型
  • pyside6 qt 事件循环
  • Secertpad搭建
  • 吞吐量、延迟、内存:深入理解垃圾回收的“三元悖论”
  • List接口和常用方法
  • 计算机一级考试网站怎么做用织梦系统做网站产权
  • Java 数据结构第二十八期:反射、枚举以及 lambda 表达式
  • Linux 磁盘分区与系统监控完全指南
  • 是普通网站地图好还是rss地图好一点网站建设申请费用
  • 使用Graphics2D创建滑块验证码
  • Flutter provide框架内部实现原理刨析
  • 关于rpm,yum,apt
  • 15.6.Bat脚本编写
  • 景德镇网站制作广告法
  • 可以做头像的网站网站区域名是什么
  • 新手记录使用uniapp-x开发鸿蒙应用
  • Linux+Apache+MySQL+PHP 架构下搭建 Discuz 社区论坛
  • 可替代Github Copilot的插件分享CodeGeeX
  • Ubuntu学习笔记
  • 双非大学生自学鸿蒙5.0零基础入门到项目实战 - 歌曲列表
  • 双非大学生自学鸿蒙5.0零基础入门到项目实战 -ArkTs核心
  • UVa 10989 Bomb Divide and Conquer
  • 【Linux】版本控制器Git和调试器—gdb/cgdb的使用
  • 怎么把个人做的网站上传到网上wordpress用户名钩子
  • 成都网站排名网站添加邮件发送怎么做
  • Spring AI 极简入门:15分钟集成AI到SpringBoot应用
  • 临潼城市建设局网站外资公司注册