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

比较useCallback、useMemo 和 React.memo

一、核心概念解析

API类型作用返回值
useCallbackReact Hook缓存函数引用记忆化的函数
useMemoReact Hook缓存计算结果记忆化的值
React.memo高阶组件(HOC)缓存组件渲染结果优化后的组件

二、详细说明与代码示例

1、useCallback: 缓存函数引用

const memoizedFn = useCallback(() => {// 函数逻辑
}, [dependencies]);
  • 解决的问题: 防止函数引用频繁变化导致子组件无效重渲染
  • 典型场景:
    • 函数作为 props 传递给优化过的子组件(React.memo
    • 函数作为其他 Hook 的依赖项(如useEffect
// 父组件
function Parent() {const [count, setCount] = useState(0);// ✅ 缓存函数引用const increment = useCallback(() => setCount(c => c + 1), []);return <Child onIncrement={increment} />;
}// 子组件(使用 React.memo 优化)
const Child = React.memo(({ onIncrement }) => {console.log('子组件渲染');return <button onClick={onIncrement}>+</button>;
});

2、useMemo:缓存计算结果

const memoizedValue = useMemo(() => {// 复杂计算return computeExpensiveValue(a, b);
}, [a, b]);
  • 解决的问题: 避免重复执行昂贵的计算
  • 典型场景:
    • 复杂计算(如数据转换、筛选)
    • 保持对象/数组引用稳定(避免作为props传递时触发重渲染)
function Component({ items }) {// ✅ 缓存计算结果const filteredItems = useMemo(() => {return items.filter(item => item.value > 100);}, [items]);return <List items={filteredItems} />;
}

React.memo: 缓存组件渲染

const MemoizedComponent = React.memo(Component, arePropsEqual?);
  • 解决的问题: 避免父组件更新导致子组件不必要的重渲染
  • 工作方式:
    • 对props进行浅比较(可自定义比较函数)
    • props未变化时复用上次渲染结果
// 基础用法
const UserCard = React.memo(({ user }) => {return <div>{user.name}</div>;
});// 自定义比较函数
const UserCard = React.memo(({ user }) => {...},(prevProps, nextProps) => prevProps.user.id === nextProps.user.id
);

三、三者区别对比

特性useCallbackuseMemoReact.memo
优化目标函数引用计算结果组件渲染
返回内容函数任何值组件
触发条件依赖变化时重建函数依赖变化时重新计算props变化时重渲染
内存开销缓存函数缓存值缓存虚拟DOM
典型使用位置组件内部组件内部组件导出时
性能影响减少子组件重渲染减少计算开销减少DOM操作

四、协同工作示例

import React, {useState, useCallback, useMemo} from 'react';// 使用React.memo优化的子组件
const Chart = React.memo((data, onClick) => {console.log('渲染');return <svg onClick={onClick}>...</svg>;
})function Dashboard() {const [data, setData] = useState([]);const [filter, setFilter] = useState('month');// ✅ 缓存函数引用const handleClick = useCallback(() => {console.log('图表点击');}, []);//✅ 缓存计算结果const filteredData = useMemo(() => {return data.filter(d => d.period === filter);}, [data, filter]);return (<div><Chartdata={filteredData}  // 稳定引用onClick={handleClick}  // 稳定引用/></div>);
}

优化效果:
1、filter变化 → filteredData重新计算 → Chart重渲染
2、父组件状态更新 → handleClick引用不变 → Chart 不重渲染
3、点击图表 → 触发缓存的handleClick

五、使用误区与最佳实践

常见错误:

// ❌ 错误1:缺少依赖项
const badCallback = useCallback(() => {console.log(count);  // 永远输出初始值
}, []);  // 缺少count 依赖// ❌ 错误2:滥用useMemo
const simpleValue = useMemo(() => 42, []);  // 直接使用 const 更高效// ❌ 错误3:期待 React.memo 深比较
React.memo(Comonent);  // 默认只做浅比较

黄金法则:
1、按需优化: 先用常规写法,出现性能问题再优化
2、组合使用:
- React.memo + useCallback 优化组件树
- useMemo + useCallback 稳定复杂依赖
3、依赖诚实: 始终声明所有依赖项
4、避免深比较: 复杂对象考虑使用ID比对而非完整对象

六、性能影响分析

操作内存开销CPU开销适用场景
使用useCallback缓存函数依赖比较函数传递/依赖项稳定化
使用useMemo缓存值依赖比较 + 计算昂贵计算/引用稳定化
使用React.memo缓存VDOMProps比较重渲染成本高的叶子组件
三者组合较高大型组件/频繁更新场景
不使用优化简单组件/无性能瓶颈

经验总结: 在10%需要优化的关键路径上使用这些API,避免在简单组件中过度优化。

http://www.xdnf.cn/news/1270837.html

相关文章:

  • 机器学习 K-Means聚类 无监督学习
  • 第4章 程序段的反复执行for语句P115练习题(题及答案)
  • 元宇宙技术如何改变社交方式?
  • 哈希与安全
  • pgAdmin 仪表盘的system部分不能显示,报SYSTEM_STATS扩展没有安装
  • C++ 中的智能指针
  • Qt 综述:从基础到一般应用
  • 机器翻译中的语言学基础详解(包括包括语法、句法和语义学等)
  • 记一次奇异的bug
  • n8n 入门指南:更适合跨境出海搞钱的AI智能体
  • 基于 InfluxDB 的服务器性能监控系统实战(一)
  • vue3上传的文件在线查看
  • 【linux基础】Linux命令提示符解析与操作指南
  • 如何在 Ubuntu 24.04 LTS Linux 上安装 Azure Data Studio
  • 编译技术的两条演化支线:从前端 UI 框架到底层编译器的智能测试
  • “自动报社保 + 查询导出 ” 的完整架构图和 Playwright C# 项目初始化模板
  • 基于IPD体系的研发项目范围管理
  • 【渲染流水线】[几何阶段]-[几何着色]以UnityURP为例
  • 202506 电子学会青少年等级考试机器人三级器人理论真题
  • 《算法导论》第 15 章 - 动态规划
  • FreeRTOS源码分析五:资源访问控制(一)
  • SOLi-LABS Page-3 (Stacked injections) --39-53关
  • OpenAI 的最新 AI 模型 GPT-5 现已在 GitHub Models 上提供!
  • 如何在 Windows 下使用 WSL 安装 Ubuntu 并配置国内镜像
  • 神经网络-local minima and saddle point
  • FFMPEG将H264转HEVC时,码率缩小多少好,以及如何通过SSIM(Structural Similarity Index结构相似性指数)衡量转码损失
  • 使用Navicat备份数据库MySQL、PostGreSQL等
  • Meta AI水印计划的致命缺陷——IEEE Spectrum深度文献精读
  • (nice!!!)(LeetCode 面试经典 150 题) 146. LRU 缓存 (哈希表+双向链表)
  • 力扣热题100------70.爬楼梯