如何使用 useMemo 和 memo 优化 React 应用性能?

使用 useMemomemo 优化 React 应用性能

在构建复杂的 React 应用时,性能优化是确保应用流畅运行的关键。React 提供了多种工具来帮助开发者优化组件的渲染和计算逻辑,其中 useMemomemo 是两个非常有用的 Hook。本文将详细介绍这两个工具的使用方法及其应用场景。

1. useMemo 的介绍与使用

1.1 什么是 useMemo

useMemo 是一个 React Hook,用于记忆(缓存)某些计算结果,以避免不必要的重复计算。它接收两个参数:一个返回值的计算函数和一个依赖项数组。只有当依赖项发生变化时,useMemo 才会重新计算并返回新的值;否则,它将返回之前缓存的结果。

1.2 useMemo 的语法
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • computeExpensiveValue(a, b) 是一个计算昂贵值的函数。
  • [a, b] 是依赖项数组,只有当这些依赖项发生变化时,useMemo 才会重新执行计算。
1.3 示例:优化总价计算

在你的 Test2.tsx 组件中,total 函数用于计算商品的总价。每次组件重新渲染时,total 都会重新计算。为了优化这一点,我们可以使用 useMemo 来缓存计算结果:

import React, { useState, useMemo } from 'react';export default function Test2() {const [search, setSearch] = useState('');const [list, setList] = useState([{ id: 1, name: '苹果', price: 10, count: 1 },{ id: 2, name: '小米', price: 20, count: 1 },{ id: 3, name: '华为', price: 30, count: 1 },]);const handleAdd = (id: number) => {setList(list.map(item => item.id === id ? { ...item, count: item.count + 1 } : item));};const handleSub = (id: number) => {setList(list.map(item => item.count > 1 && item.id === id ? { ...item, count: item.count - 1 } : item));};// 使用 useMemo 缓存总价计算结果const total = useMemo(() => {return list.reduce((pre, cur) => pre + cur.price * cur.count, 0);}, [list]);return (<div><h1>父组件</h1><input type="text" value={search} onChange={(e) => setSearch(e.target.value)} /><table border={1} cellPadding={5} cellSpacing={0}><thead><tr><th>商品名称</th><th>商品价格</th><th>商品数量</th></tr></thead><tbody>{list.map(item => (<tr key={item.id}><td>{item.name}</td><td>{item.price * item.count}</td><td><button onClick={() => handleAdd(item.id)}>+</button><span>{item.count}</span><button onClick={() => handleSub(item.id)}>-</button></td></tr>))}</tbody><tfoot><tr><th scope="row" colSpan={1}>总价</th><td>{total}</td></tr></tfoot></table></div>);
}

在这个例子中,useMemo 确保只有当 list 发生变化时才会重新计算 total,从而减少了不必要的计算开销。

2. memo 的介绍与使用

2.1 什么是 memo

memo 是 React 提供的一个高阶组件(HOC),用于防止子组件不必要的重新渲染。它通过比较当前和上次渲染的 props 来决定是否需要重新渲染组件。如果 props 没有变化,则跳过渲染,直接复用之前的渲染结果。

2.2 memo 的语法
const MemoizedComponent = React.memo(MyComponent);
  • MyComponent 是你想要优化的组件。
  • React.memo 返回一个新的组件,该组件会在 props 没有变化时不重新渲染。
2.3 示例:优化子组件渲染

假设我们有一个子组件 ProductItem,它负责显示单个商品的信息。我们可以使用 memo 来优化这个组件,避免不必要的重新渲染:

import React from 'react';
import { memo } from 'react';interface ProductItemProps {product: { id: number; name: string; price: number; count: number };onAdd: () => void;onSub: () => void;
}const ProductItem: React.FC<ProductItemProps> = ({ product, onAdd, onSub }) => {console.log('ProductItem rendered');return (<tr key={product.id}><td>{product.name}</td><td>{product.price * product.count}</td><td><button onClick={onAdd}>+</button><span>{product.count}</span><button onClick={onSub}>-</button></td></tr>);
};// 使用 memo 包装 ProductItem 组件
const MemoizedProductItem = memo(ProductItem);export default MemoizedProductItem;

在这个例子中,MemoizedProductItem 只会在其 props 发生变化时重新渲染,否则会复用之前的渲染结果,从而提高性能。

3. useMemomemo 的区别

  • 作用范围

    • useMemo 用于优化组件内部的计算逻辑,减少不必要的计算。
    • memo 用于优化组件的渲染行为,减少不必要的重新渲染。
  • 使用场景

    • 当你在组件内部有复杂的计算逻辑时,可以使用 useMemo 来缓存计算结果。
    • 当你有一个子组件频繁重新渲染但实际内容没有变化时,可以使用 memo 来优化渲染性能。

4. 总结

useMemomemo 是 React 中非常强大的工具,能够显著提升应用的性能。合理使用它们可以帮助你避免不必要的计算和渲染,从而让应用更加高效和流畅。希望本文能帮助你更好地理解和使用这两个工具,为你的 React 应用带来更好的用户体验。

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

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

相关文章

Agent Laboratory: Using LLM Agents as Research Assistants 论文简介

加速机器学习研究的智能实验室——Agent Laboratory 1. 引言 随着人工智能技术的飞速发展&#xff0c;机器学习领域正以前所未有的速度推进科学发现和技术创新。然而&#xff0c;传统的科学研究模式往往受到时间、资源和专业知识限制&#xff0c;阻碍了研究者们探索新想法的能…

【网络协议】【http】【https】ECDHE-TLS1.2

【网络协议】【http】【https】ECDHE-TLS1.2 ECDHE算法 1.客户端和服务器端事先确定好使用哪种椭圆曲线&#xff0c;和曲线上的基点G&#xff0c;这两个参数都是公开的&#xff0c; 双方各自随机生成一个随机数作为私钥d&#xff0c;并与基点 G相乘得到公钥Q(QdG)&#xff0c…

规避路由冲突

路由冲突是指在网络中存在两个或多个路由器在进行路由选择时出现矛盾&#xff0c;导致网络数据包无法正确传输&#xff0c;影响网络的正常运行。为了规避路由冲突&#xff0c;可以采取以下措施&#xff1a; 一、合理规划IP地址 分配唯一IP&#xff1a;确保每个设备在网络中都有…

项目实战--网页五子棋(游戏大厅)(3)

我们的游戏大厅界面主要需要包含两个功能&#xff0c;一是显示用户信息&#xff0c;二是匹配游戏按钮 1. 页面实现 hall.html <!DOCTYPE html> <html lang"ch"> <head><meta charset"UTF-8"><meta name"viewport"…

大模型UI:Gradio全解11——Chatbot:融合大模型的聊天机器人(4)

大模型UI&#xff1a;Gradio全解11——Chatbot&#xff1a;融合大模型的聊天机器人&#xff08;4&#xff09; 前言本篇摘要11. Chatbot&#xff1a;融合大模型的多模态聊天机器人11.4 使用Blocks创建自定义聊天机器人11.4.1 简单聊天机器人演示11.4.2 立即响应和流式传输11.4.…

【线性代数】行列式的概念

d e t ( A ) ∑ i 1 , i 2 , ⋯ , i n ( − 1 ) σ ( i 1 , ⋯ , i n ) a 1 , i 1 a 2 , i 2 , ⋯ , a n , i n det(A) \sum_{i_1,i_2,\cdots,i_n } (-1)^{\sigma(i_1,\cdots,i_n)} a_{1,i_1}a_{2,i_2},\cdots, a_{n,i_n} det(A)i1​,i2​,⋯,in​∑​(−1)σ(i1​,⋯,in​)a1…

关于php语言api接口开发的流程

确定接口需求&#xff1a;首先明确接口的功能和需求&#xff0c;包括输入参数、输出结果以及接口的业务逻辑。 设计接口路由&#xff1a;根据接口需求&#xff0c;设计具体的接口路由&#xff0c;即URL路径&#xff0c;用于访问接口。 搭建PHP环境&#xff1a;确保你的服务器上…

STM32 FreeRTOS内存管理简介

在使用 FreeRTOS 创建任务、队列、信号量等对象时&#xff0c;通常都有动态创建和静态创建的方式。动态方式提供了更灵活的内存管理&#xff0c;而静态方式则更注重内存的静态分配和控制。 如果是1的&#xff0c;那么标准 C 库 malloc() 和 free() 函数有时可用于此目的&#…

【Linux系统编程】—— 深度解析进程等待与终止:系统高效运行的关键

文章目录 进程创建再次认识fork()函数fork()函数返回值 写时拷贝fork常规⽤法以及调用失败的原因 进程终⽌进程终止对应的三种情况进程常⻅退出⽅法_exit函数exit函数return退出 进程等待进程等待的必要性进程等待的⽅法 进程创建 再次认识fork()函数 fork函数初识&#xff1…

国产编辑器EverEdit -重复行

1 重复行 1.1 应用场景 在代码或文本编辑过程中&#xff0c; 经常需要快速复制当前行&#xff0c;比如&#xff0c;给对象的多个属性进行赋值。传统的做法是&#xff1a;选中行-> 复制-> 插入新行-> 粘贴&#xff0c;该操作有4个步骤&#xff0c;非常繁琐。 那有没…

基于VSCode+CMake+debootstrap搭建Ubuntu交叉编译开发环境

基于VSCodeCMakedebootstrap搭建Ubuntu交叉编译开发环境 1 基于debootstrap搭建目标系统环境1.1 安装必要软件包1.2 创建sysroot目录1.3 运行debootstrap1.4 挂载必要的虚拟文件系统1.5 进入目标系统1.6 使用目标系统&#xff08;以安装zlog为例&#xff09;1.7 清理和退出 2 基…

NiceFish(美人鱼)

前端有 3 个版本&#xff1a; 浏览器环境移动端环境Electron 环境 服务端有 2 个版本&#xff1a; SpringBoot 版本&#xff08;已实现基于 Apache Shiro 的 RBAC 权限控制&#xff09;SpringCloud 版本 1.主要依赖 名称版本描述Angular16.2.0Angular 核心库。PrimeNG16.2…

华为ENSP:STP和链路聚合的管理与配置

这里将不再过度阐述STP和链路聚合的理论知识&#xff0c;不清楚的同学可以去观看Cisco文章中的理论知识 理论知识https://blog.csdn.net/2301_76341691/article/details/145166547?fromshareblogdetail&sharetypeblogdetail&sharerId145166547&sharereferPC&…

【PyCharm】连接 Git

【PyCharm】相关链接 【PyCharm】连接 Git【PyCharm】连接Jupyter Notebook【PyCharm】快捷键使用【PyCharm】远程连接Linux服务器【PyCharm】设置为中文界面 要在 PyCharm 中连接 Git&#xff0c;确保您的开发环境已经安装了 Git&#xff0c;并且 PyCharm 能够访问它。 以下…

dl学习笔记:(4)简单神经网络

&#xff08;1&#xff09;单层正向回归网络 bx1x2z100-0.2110-0.05101-0.051110.1 接下来我们用代码实现这组线性回归数据 import torch x torch.tensor([[1,0,0],[1,1,0],[1,0,1],[1,1,1]], dtype torch.float32) z torch.tensor([-0.2, -0.05, -0.05, 0.1]) w torch.…

三、华为交换机 Hybrid

一、Hybrid功能 Hybrid口既可以连接普通终端的接入链路&#xff08;类似于Access接口&#xff09;&#xff0c;又可以连接交换机间的干道链路&#xff08;类似于Trunk接口&#xff09;。它允许多个VLAN的帧通过&#xff0c;并可以在出接口方向将某些VLAN帧的标签剥掉&#xff0…

Tensor 基本操作1 | PyTorch 深度学习实战

目录 创建 Tensor常用操作unsqueezesqueezeSoftmax代码1代码2代码3 argmaxitem 创建 Tensor 使用 Torch 接口创建 Tensor import torch参考&#xff1a;https://pytorch.org/tutorials/beginner/basics/tensorqs_tutorial.html 常用操作 unsqueeze 将多维数组解套&#xf…

Grafana系列之面板接入Prometheus Alertmanager

关于Grafana的仪表板Dashboard&#xff0c;以及面板Panel&#xff0c;参考Grafana系列之Dashboard。可以直接在面板上创建Alert&#xff0c;即所谓的Grafana Alert&#xff0c;参考Grafana系列之Grafana Alert。除了Grafana Alert外&#xff0c;面板也可接入Prometheus Alertma…

Windows 上安装 MongoDB 的 zip 包

博主介绍&#xff1a; 大家好&#xff0c;我是想成为Super的Yuperman&#xff0c;互联网宇宙厂经验&#xff0c;17年医疗健康行业的码拉松奔跑者&#xff0c;曾担任技术专家、架构师、研发总监负责和主导多个应用架构。 近期专注&#xff1a; RPA应用研究&#xff0c;主流厂商产…

LeetCode 2266.统计打字方案数:排列组合

【LetMeFly】2266.统计打字方案数&#xff1a;排列组合 力扣题目链接&#xff1a;https://leetcode.cn/problems/count-number-of-texts/ Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。 为了 打出 一个字母&#xff0c;Alice 需要 按 对应字母 i 次&#xff0c…