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

React 第十七节 useMemo用法详解

概述

useMemo 是React 中的一个HOOK,用于根据依赖在每次渲染时候缓存计算结果
大白话就是,只有依赖项发生变化时候,才会重新渲染为新计算的值,否则就还是取原来的值,有点类似 vue 中的 computed 计算属性,注意与 useEffect 区分;

写法

const value = useMemo(fnc, [a,b])

第一个参数fnc 是一个函数,用于根据 依赖项 a、b变化时候触发计算得出新值,必须是一个没有任何参数的纯函数,可以返回任意类型;若 a、b没有变化,则React 返回与上次相同的值;若 a、b 发生改变,则会返回新的值;
第二个参数[a、b] 是一个数组,函数 fnc中计算所依赖的值,这个数组中若不传入具体变量,而是传入 空数组[],那么会在组件每次更新时候重新渲染;

这种缓存值的方式叫做 记忆化 (memoization), 这也是这个Hook 称为 useMemo 的由来

使用场景

1、当我们在 useMemo 中的代码运行很慢,通过使用 useMemo 运行效率得到显著提升;
2、将计算结果作为 props 传递给包裹在 memo 中的组件。当计算结果没有改变时,你会想跳过重新渲染。记忆化让组件仅在依赖项不同时才重新渲染。
3、你传递的值稍后用作某些 Hook 的依赖项。例如,也许另一个 useMemo 计算值依赖它,或者 useEffect 依赖这个值。

例如:
将计算结果作为 props 传给子组件

// 父组件
import React, {useMemo, useState} from 'react'
import ChildA from './childA'
export default function MyMemo() {const [firstName, setFirstName] = useState('Andy')const [lastName, setLastName] = useState('Li')const [count, setCount] = useState(0)const fullName = useMemo(() => {console.log('==useMemo==')return firstName +'' + lastName}, [firstName, lastName]) // 第二个参数是数组,表示fullName 依赖 firstName 和 lastName 的值,只有 firstName 和 lastName 值发生变化,fullName 才重新计算const handleChangeName = (e, type) => {console.log('==handleChangeName==', e)// [`set${type}`](e.target.value)// if (type === 'FirstName') {//     setFirstName(e.target.value)// } else {//     setLastName(e.target.value)// }}const handleChangeFirstName = () => {console.log('==更新第一个名称=')setCount(count+1)setFirstName(11)}return (<div><input type="text"  value={firstName} onChange={(e) => handleChangeName(e, 'FirstName')} /><p>点击了{count}</p><button onClick={handleChangeFirstName}>firstName</button><br/><input type="text" value={lastName} onChange={(e) => handleChangeName(e, 'LastName')} /><hr /><ChildA fullName={fullName}></ChildA></div>)
}
// 子组件
import React, {memo, useState} from 'react'
const ChildA = memo(({fullName}) =>{console.log('=render=ChildA==fullName----', fullName)return (<div><p>全称:{fullName}</p></div>)
})
export default ChildA

在这里插入图片描述
通过 log日志,我们可以发现,共计点击了 firstName 按钮 18次;只有在初始化第一次点击时候才会渲染 子组件;
因为第一次点击将 firstName 更新为 11;之后的点击传入相同的值 11,导致 useMemo 返回的 fullName 是相同的,故不再进行渲染

而当我们使用 useEffect 时候,会每次都更新子组件

注意:

1、useMemo 只能作为组件代码性能优化使用,如果在不使用 useMemo时,代码无法正常运行,那么我们需要先排查问题,之后再使用 useMemo
2、避免不必要的更新 state 的 Effect;React 中很多的性能是由于其自身的更新链导致的,所以我们要避免重复的更新同一个组件
3、尽可能的减少依赖项,避免过多的依赖导致代码难以理解,难以追踪问题;我们可以将依赖项 设置成 state;
4、我们应该减少状态的提升,多使用state,而不是滥用useMemo来处理性能;

相关文章:

React 第十七节 useMemo用法详解

概述 useMemo 是React 中的一个HOOK&#xff0c;用于根据依赖在每次渲染时候缓存计算结果&#xff1b; 大白话就是&#xff0c;只有依赖项发生变化时候&#xff0c;才会重新渲染为新计算的值&#xff0c;否则就还是取原来的值&#xff0c;有点类似 vue 中的 computed 计算属性…...

鸿蒙项目云捐助第十五讲云数据库的初步使用

鸿蒙项目云捐助第十五讲云数据库的初步使用 在华为云技术使用中&#xff0c;前面使用了云函数&#xff0c;接下来看一下华为云技术中的另外一个技术云数据库的使用。 一、云数据库的创建 这里使用华为云数据库也需要登录到AppGallery Connect平台中&#xff0c;点击进入到之…...

如何构建一个可信的联邦RAG系统。

今天给大家分享一篇论文。 题目是&#xff1a;C-RAG&#xff1a;如何构建一个可信的联邦检索RAG系统。 论文链接:https://arxiv.org/abs/2412.13163 论文概述 尽管大型语言模型 (LLM) 在各种应用中展现出令人印象深刻的能力&#xff0c;但它们仍然存在可信度问题&#xff…...

【深度学习之三】FPN与PAN网络详解

FPN与PAN&#xff1a;深度学习中的特征金字塔网络与路径聚合网络 在深度学习的领域里&#xff0c;特征金字塔网络&#xff08;Feature Pyramid Networks&#xff0c;简称FPN&#xff09; 和 路径聚合网络&#xff08;Path Aggregation Network&#xff0c;简称PAN&#xff09;…...

Qt学习笔记第71到80讲

第71讲 事件过滤器的方式实现滚轮按键放大 事件体系&#xff08;事件派发 -> 事件过滤->事件分发->事件处理&#xff09;中&#xff0c;程序员主要操作的是事件分发与事件处理。我们之前已经通过继承QTextEdit来重写事件实现Ctrl加滚轮的检测&#xff0c;还有一种处理…...

以管理员身份运行

同时按下Ctrl Shift Esc键打开任务管理器&#xff0c;在任务管理器的左上角&#xff0c;点击“文件”菜单&#xff0c;在下拉菜单中选择“新建任务” 在弹出的对话框中&#xff0c;输入您想要运行的程序的名称。如果您不确定程序的确切名称&#xff0c;可以点击“浏览”来找到…...

用 Python 实现井字棋游戏

一、引言 井字棋&#xff08;Tic-Tac-Toe&#xff09;是一款经典的两人棋类游戏。在这个游戏中&#xff0c;玩家轮流在 3x3 的棋盘上放置自己的标记&#xff0c;通常是 “X” 和 “O”&#xff0c;第一个在棋盘上连成一线&#xff08;横、竖或斜&#xff09;的玩家即为获胜者。…...

06 实现自定义AXI DMA驱动

为什么要实现自定义AXI DMA驱动 ZYNQ 的 AXI DMA 在 Direct Register DMA &#xff08;即 Simple DMA&#xff09;模式下可以通过 AXIS 总线的 tlast 提前结束传输&#xff0c;同时还可以在 BUFFLEN 寄存器中读取到实际传输的字节数&#xff0c;但是通过 Linux 的 DMA 驱动框架…...

SpringBoot集成ENC对配置文件进行加密

在线MD5生成工具 配置文件加密&#xff0c;集成ENC 引入POM依赖 <!-- ENC配置文件加密 --><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>2.1.2</ver…...

初学stm32 ——— 串口通信

目录 STM32的串口通信接口 UART异步通信方式特点&#xff1a; 串口通信过程 STM32串口异步通信需要定义的参数: USART框图&#xff1a; 常用的串口相关寄存器 串口操作相关库函数 ​编辑 串口配置的一般步骤 STM32的串口通信接口 UART&#xff1a;通用异步收发器USART&am…...

qwt 多Y轴 项目效果

项目场景&#xff1a; 在做一个半导体上位机软件项目实践中&#xff0c;需要做一个曲线展示和分析界面&#xff0c;上位机主题是用qt框架来开发&#xff0c;考虑到目前qt框架的两种图标库&#xff0c;一个是qcustomplot 一个是 qwt。之所以采用qwt &#xff0c;根本原因是因为…...

Java中通过ArrayList扩展数组

在Java中&#xff0c;ArrayList 是一个动态数组实现&#xff0c;能够根据需要自动调整其大小。与传统的数组不同&#xff0c;ArrayList 不需要预先指定大小&#xff0c;并且提供了许多方便的方法来操作集合中的元素。下面将详细介绍如何使用 ArrayList 进行数组的扩展&#xff…...

Java:链接redis报错:NoSuchElementException: Unable to validate object

目录 前言报错信息排查1、确认redis密码设置是否有效2、确认程序配置文件&#xff0c;是否配置了正确的redis登录密码3、检测是否是redis持久化的问题4、确认程序读取到的redis密码没有乱码 原因解决 前言 一个已经上线的项目&#xff0c;生产环境的redis居然没有设置密码&…...

datasets库之load_dataset

目录 问题解决方案 问题 使用peft用lora微调blip2时用到了一个足球数据集&#xff0c;如下&#xff1a; 原始代码如下 dataset load_dataset("ybelkada/football-dataset", split"train")然而这需要梯子才能下载&#xff0c;服务器较难用VPN所以使用au…...

React Router常见面试题目

1. React Router 支持哪几种模式? React Router 支持以下两种主要模式&#xff1a; BrowserRouter (基于 HTML5 History API 的模式) 原理&#xff1a; 利用 history.pushState 和 history.replaceState 操作浏览器历史栈&#xff0c;无需重新加载页面。URL 看起来像传统 URL…...

sequelize-cli 封装登录接口

node ORM &#xff08;sequelize&#xff09;使用、查询、验证及express 基础框架的搭建及实例的使用 一、思路 第一步&#xff1a;肯定是用户要向接口传递邮箱、账号和密码了。 第二步&#xff1a;接口这边&#xff0c;先要验证。因为这里不是往数据库里存储数据&#xff0c;…...

使用 Elasticsearch 查询和数据同步的实现方法

在开发过程中&#xff0c;将数据从数据库同步到 Elasticsearch (ES) 是常见的需求之一。本文将重点介绍如何通过 Python 脚本将数据库中的数据插入或更新到 Elasticsearch&#xff0c;并基于多字段的唯一性来判断是否执行插入或更新操作。此外&#xff0c;我们还将深入探讨如何…...

QTday1作业设置简易登录界面

代码 #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//创建一个标签QLabel *lab1 new QLabel(this);//重新设置大小lab1->resize(1925,1080);//用动图类QMovie实例化一个动图QMovie *mv new QMovie("C:\\Users\\MR\\Deskto…...

RC低通滤波器和LR低通滤波器,LC低通滤波器该怎么选择

这是RC低通滤波器利用电容两端的电压不能突变可以滤除高频噪声 这是LR低通滤波器利用流过电感的电流不能突变也可以滤除高频噪声 那么问题来了两个低通滤波器&#xff0c;该怎么选择呢还是随便选一个就好&#xff1f; RC电路&#xff1a;因为电流电阻会发热耗能&#xff0c;所…...

芯旺微KF32A156芯片ADC配置

使用芯旺微KF32A156的芯片做预研项目&#xff0c;使用了ADC0外设&#xff0c;根据芯片规格书中的描述进行了配置&#xff1a; /*** brief: Configure ADC.** param[in] none.* param[in] none.* param[out] None* retval: None*/ static void adc_peripheral_init(void) …...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

Python的__call__ 方法

在 Python 中&#xff0c;__call__ 是一个特殊的魔术方法&#xff08;magic method&#xff09;&#xff0c;它允许一个类的实例像函数一样被调用。当你在一个对象后面加上 () 并执行时&#xff08;例如 obj()&#xff09;&#xff0c;Python 会自动调用该对象的 __call__ 方法…...

Python第七周作业

Python第七周作业 文章目录 Python第七周作业 1.使用open以只读模式打开文件data.txt&#xff0c;并逐行打印内容 2.使用pathlib模块获取当前脚本的绝对路径&#xff0c;并创建logs目录&#xff08;若不存在&#xff09; 3.递归遍历目录data&#xff0c;输出所有.csv文件的路径…...