React.memo、useMemo 和 React.PureComponent的区别

useMemo 和 React.memo 都是 React 提供的性能优化工具,但它们的作用和使用场景有显著不同。以下是两者的全面对比:

一、核心区别总结

特性useMemoReact.memo
类型React Hook高阶组件(HOC)
作用对象缓存计算结果缓存组件渲染结果
优化目标避免重复计算避免不必要的子组件重新渲染
触发条件依赖项变化时重新计算props变化时重新渲染
使用位置组件内部组件定义外层
返回值记忆化的值记忆化的组件

二、useMemo 深度解析

1、基本用法

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

2、主要特点

  • 缓存计算值:只有当依赖项变化时才重新计算
  • 组件内部使用:只能在函数组件或自定义Hook中使用
  • 不阻止渲染:只是优化计算过程,不影响组件是否渲染

3、典型场景

function Component({ items }) {// 只有items变化时才重新计算排序结果const sortedItems = useMemo(() => {return items.sort((a, b) => a.value - b.value);}, [items]);return <List items={sortedItems} />;
}

三、React.memo 深度解析

1、基本用法

const MemoizedComponent = React.memo(Component, arePropsEqual?);

注意:这里传递了第二个参数,它是一个自定义比较函数,用于决定是否跳过重新渲染 比如下面案例中 当判断条件为true时候 跳过渲染

2、主要特点

  • 组件记忆化:对组件进行浅比较,props不变时跳过渲染
  • 类似PureComponent:用于函数组件的shouldComponentUpdate
  • 可自定义比较:通过第二个参数控制比较逻辑

3、典型场景

const Child = React.memo(function Child({ data }) {return <div>{data.value}</div>;
});function Parent() {const [count, setCount] = useState(0);return (<><button onClick={() => setCount(c => c + 1)}>Re-render Parent</button><Child data={{ value: "Static" }} /> {/* 不会随Parent重渲染 */}</>);
}

四、关键区别

1、作用层次不同

  • useMemo:优化组件内部的计算过程
  • React.memo:优化整个组件的渲染行为

2、依赖检测方式

// useMemo 显式声明依赖
const value = useMemo(() => a + b, [a, b]);// React.memo 自动浅比较props
const MemoComp = React.memo(Comp);
// 或自定义比较
const MemoComp = React.memo(Comp, (prev, next) => prev.id === next.id); // 当上一次值和这次值的id 不一样的时候  就会触发渲染

3、性能影响对比

操作useMemo影响React.memo影响
组件重新渲染仍会执行,但可能跳过计算可能完全跳过子组件渲染
内存占用缓存计算结果缓存组件实例
适用粒度细粒度(单个值)粗粒度(整个组件)

五、联合使用示例

// 优化计算 + 优化渲染的完美组合
const ExpensiveComponent = React.memo(function({ items }) {const processedItems = useMemo(() => {return items.map(item => ({...item,fullName: `${item.firstName} ${item.lastName}`}));}, [items]);return (<ul>{processedItems.map(item => (<li key={item.id}>{item.fullName}</li>))}</ul>);
});function Parent() {const [count, setCount] = useState(0);const [items] = useState([...]);return (<><button onClick={() => setCount(c => c + 1)}>Render {count}</button><ExpensiveComponent items={items} /> {/* 父组件重渲染时,子组件不会重新渲染 */}</>);
}

六、使用建议

  • 优先考虑 React.memo:当需要防止不必要的子组件重渲染时
  • 合理使用 useMemo:对于计算量大的派生数据
  • 不要过度优化:简单的组件和计算不需要使用
  • 注意引用类型:两者都依赖浅比较,注意对象/数组的引用稳定性

七、常见误区

1、错误期待

// 以为能阻止子组件渲染(实际无效)
const Child = () => {const data = useMemo(() => ({ value: 1 }), []);return <div>{data.value}</div>;
}
// 正确做法是用React.memo包裹组件

2、错误依赖

// 依赖项不全可能导致过时闭包
const value = useMemo(() => a + b + c, [a, b]); // 缺少c

3、错误嵌套

// 不需要用useMemo缓存React.memo组件
const MemoComp = useMemo(() => React.memo(Comp), []); // 多余

八、React.memo和React.PureComponent区别

1、PureComponent 的核心作用

  • 自动实现 shouldComponentUpdate()普通 React.Component 在父组件更新或自身状态变化时总会重新渲染,而 PureComponent 会先浅比较 props 和 state,只有数据真正变化时才会触发渲染
  • 避免不必要的渲染,适用于数据变化不频繁或props/state 是简单类型(非深层嵌套对象) 的场景。

2、与 React.Component 的区别

特性React.ComponentReact.PureComponent
是否自动比较 props/state❌ 每次父组件更新或自身状态变化都会重新渲染✅ 仅当 props/state 浅比较不同时才重新渲染
适用场景需要手动优化或复杂数据变化时数据简单、变化不频繁时
性能优化需要手动实现shouldComponentUpdate()自动优化,减少不必要的渲染

3、适用场景

✅ 推荐使用 PureComponent 的情况:

  • props/state 是基本类型(string, number, boolean 等)
  • props/state 是简单对象(没有深层嵌套)
  • 组件渲染成本高(如长列表、复杂计算)

❌ 不推荐使用 PureComponent 的情况:

  • props/state 包含深层嵌套对象(浅比较无法检测内部变化)
  • 使用了可变数据(如直接修改数组或对象)
  • 需要自定义 shouldComponentUpdate 逻辑

4、代码示例

import React from 'react';// 使用 PureComponent 替代 Component
class MyComponent extends React.PureComponent {render() {console.log("只有 props/state 变化时才会重新渲染!");return <div>{this.props.value}</div>;}
}

5、注意事项

1、 浅比较(shallow compare)的局限性:PureComponent 只对比 props/state 的第一层,如果数据是深层嵌套的(如 { user: { name: ‘Alice’ } }),修改 user.name 不会触发重新渲染(因为 user 对象的引用没变
2、避免直接修改 state(应使用不可变数据)

// ❌ 错误:直接修改数组,PureComponent 无法检测变化
this.state.items.push(newItem);
this.setState({ items: this.state.items }); // 不会触发重新渲染// ✅ 正确:返回新数组
this.setState({ items: [...this.state.items, newItem] }); // 会触发重新渲染

九、PureComponent 和 React.memo 的区别

1、适用组件类型不同

却别PureComponentReact.memo
适用组件Class 组件函数组件
替代方案继承 React.PureComponent用 React.memo() 包裹函数组件
示例class MyComp extends React.PureComponentconst MyComp = React.memo(() => {…})

2、比较方式

两者都默认使用 浅比较(shallow compare),但 React.memo 更灵活:

  • PureComponent:自动比较 props 和 state,只要其中任何一个变化就重新渲染
  • React.memo:默认只比较 props(函数组件没有 state),但可以自定义比较逻辑

3、对 state 的处理

PureComponentReact.memo
是否比较 state✅ 比较 props 和 state❌ 只比较 props(函数组件依赖 useState/useReducer 管理状态
状态变化是否触发渲染✅ state 变化会触发重新渲染❌ state 变化不影响 memo(由 React Hooks 内部处理)

4、使用场景

✅ PureComponent 适用场景:

  • Class 组件,且 props/state 是简单数据类型或浅层对象
  • 不需要自定义 shouldComponentUpdate 逻辑

✅ React.memo 适用场景:

  • 函数组件,且 props 是简单数据类型或浅层对象
  • 需要自定义比较逻辑(如深层比较某些 props)

5、代码对比

(1)PureComponent(Class 组件)

import React from 'react';class MyComponent extends React.PureComponent {render() {return <div>{this.props.value}</div>;}
}

(2)React.memo(函数组件)

import React from 'react';const MyComponent = React.memo(function MyComponent(props) {return <div>{props.value}</div>;
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/93183.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/93183.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lumerical INTERCONNECT ------ CW Laser 和 OPWM 组成的系统

Lumerical INTERCONNECT ------ CW Laser 和 OPWM 组成的系统 引言 正文 引言 这里我们来简单介绍一下 CW Laser 与 OSA 组成的简单系统结构的仿真。 正文 我们构建一个如下图所示的仿真结构。 我们将 CWL 中的 power 设置为 1 W。 然后直接运行仿真查看结果如下: 虽然 …

想涨薪30%?别只盯着大厂了!转型AI产品经理的3个通用方法,人人都能学!

在AI产品经理刚成为互联网公司香饽饽的时候&#xff0c;刚做产品1年的月月就规划了自己的转型计划&#xff0c;然后用3个月时间成功更换赛道&#xff0c;转战AI产品经理&#xff0c;涨薪30%。 问及她有什么上岸秘诀&#xff1f;她也复盘总结了3个踩坑经验和正确路径&#xff0c…

基于Hadoop的全国农产品批发价格数据分析与可视化与价格预测研究

文章目录有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍每文一语有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 随着我国农业数字化进程的加快&#xff0c;农产品批发市场每天都会产生海量的价格…

STM32在使用DMA发送和接收时的模式区别

在STM32的DMA传输中&#xff0c;发送使用DMA_Mode_Normal而接收使用DMA_Mode_Circular的设计基于以下关键差异&#xff1a;1. ‌触发机制的本质区别‌‌发送方向&#xff08;TX&#xff09;‌&#xff1a;由USART的‌TXE标志&#xff08;发送寄存器空&#xff09;触发‌&#x…

【秋招笔试】2025.08.15饿了么秋招机考-第三题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围在线刷题 bishipass.com 03. A先生的商贸网络投资 问题描述 A先生是一位精明的商人,他计划在 n n n 个城市之间建立商贸网络。目前有 m m

Socket 套接字的学习--UDP

上次我们大概介绍了一些关于网络的基础知识&#xff0c;这次我们利用编程来深入学习一下一&#xff1a;套接字Socket1.1什么是Socketsocket API 是一层抽象的网络编程接口,适用于各种底层网络协议,如 IPv4、IPv6,. 然而, 各种网络协议的地址格式并不相同。1.2套接字的分类套接字…

AI - MCP 协议(一)

AI应用开发的高级特性——MCP模型上下文协议&#xff0c;打通AI与外部服务的边界。 ************************************************************************************************************** 一、需求分析 当你的AI具备了RAG的能力&#xff0c;具备了调用工具的…

在es中安装kibana

一 安装 1.1 验证访问https的连通性 # 测试 80 端口&#xff08;HTTP&#xff09; curl -I -m 5 http://目标IP:端口号 说明&#xff1a; -I&#xff1a;仅获取 HTTP 头部&#xff08;Head 请求&#xff09;&#xff0c;不下载正文&#xff0c;减少数据传输。 -m 5&#x…

嵌入式开发学习———Linux环境下网络编程学习(二)

UDP服务器客户端搭建UDP服务器代码#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h>#define PORT 8080 #define BUFFER_SIZE 1024int main() {int sockfd;char buffer[BUFFER_SIZE…

UVa1465/LA4841 Searchlights

UVa12345 UVa1465/LA4841 Searchlights题目链接题意输入格式输出格式分析AC 代码题目链接 本题是2010年icpc亚洲区域赛杭州赛区的I题 题意 在一个 n 行 m 列&#xff08;n≤100&#xff0c;m≤10 000&#xff09;的网格中有一些探照灯&#xff0c;每个探照灯有一个最大亮度 k&…

详解区块链技术及主流区块链框架对比

文章目录一、区块链技术栈详解二、主流区块链框架对比1. 公有链&#xff08;Public Blockchain&#xff09;2. 联盟链&#xff08;Consortium Blockchain&#xff09;3. 私有链&#xff08;Private Blockchain&#xff09;三、技术选型建议1. 按需求选择框架2. 开发工具与生态四…

大模型 + 垂直场景:搜索 / 推荐 / 营销 / 客服领域开发有哪些新玩法?

技术文章大纲&#xff1a;大模型 垂直场景的新玩法大模型与搜索领域的结合大模型在搜索领域的应用可以显著提升搜索结果的准确性和用户体验。利用大模型进行语义理解和上下文关联&#xff0c;能够实现更精准的意图识别。结合知识图谱和动态索引优化&#xff0c;可以增强长尾查…

p5.js 3D盒子的基础用法

点赞 关注 收藏 学会了 如果你刚接触 p5.js&#xff0c;想尝试 3D 绘图&#xff0c;那么box()函数绝对是你的入门首选。它能快速绘制出 3D 长方体&#xff08;或正方体&#xff09;&#xff0c;配合简单的交互就能做出酷炫的 3D 效果。本文会从基础到进阶&#xff0c;带你吃…

【动态规划 完全背包 卡常】P9743 「KDOI-06-J」旅行|普及+

本文涉及知识点 C动态规划 完全背包 C记忆化搜索 「KDOI-06-J」旅行 题目描述 小 C 在 C 国旅行。 C 国有 nmn\times mnm 个城市&#xff0c;可以看做 nmn\times mnm 的网格。定义 (i,j)(i,j)(i,j) 表示在网格中第 iii 行第 jjj 列的城市。 该国有 222 种交通系统&#x…

pytest框架-详解

目录 一、前言 二、pytest安装 2.1、安装 2.2、验证安装 2.3、pytest文档 三、pytest框架的约束 3.1、 python的命名规则 3.2、 pytest的命名规则 四、pytest的运行方式 4.1、主函数运行 4.2、命令行运行 五、pytest配置文件pytest.ini文件 六、前置和后置 七、as…

【递归、搜索与回溯算法】DFS解决FloodFill算法

FloodFill算法简介一、[图像渲染](https://leetcode.cn/problems/flood-fill/description/)二、[岛屿数量](https://leetcode.cn/problems/number-of-islands/description/)三、[岛屿的最大面积](https://leetcode.cn/problems/max-area-of-island/description/)四、[被围绕的区…

解决网络传输中可能出现的“粘包”

先理解核心问题&#xff1a;什么是“TCP粘包”&#xff1f; TCP 就像一条水管&#xff0c;数据通过水管从一端传到另一端。但它有个特点&#xff1a;不会按“发送时的小包”来划分&#xff0c;而是把数据当成连续的字节流。 比如&#xff1a; 你分两次发数据&#xff1a;第一次…

Docker搭建RSS订阅服务(freshRss+rsshub)

目录搭建freshRss1. 创建yml文件2. 创建容器3. 检查容器状态&#xff0c;正常运行则搭建成功4. 浏览器访问并配置数据库5. 开始使用搭建RssHub1. 创建yml文件2. 创建容器3. 检查容器状态&#xff0c;正常运行则搭建成功4. 浏览器访问生成RSS路由&#xff08;订阅地址&#xff0…

Spring 条件注解与 SPI 机制(深度解析)

在 Spring 及 Spring Boot 框架中&#xff0c;条件注解与 SPI 机制扮演着至关重要的角色&#xff0c;它们是实现自动配置、灵活控制 Bean 创建以及组件按需加载的关键所在。深入理解它们的底层实现与应用场景&#xff0c;既能帮助我们在面试中对答如流&#xff0c;又能在实际开…

Mac(二)Homebrew 的安装和使用

官网地址&#xff1a; https://brew.sh/官方文档&#xff1a; https://docs.brew.sh/Manpage Homebrew 是 macOS 上最强大的包管理器&#xff0c;让你轻松安装、更新和管理成千上万的开发工具、命令行程序&#xff08;如 wget, tree, ffmpeg&#xff09;甚至图形应用&#xff0…