WHAT - React 函数与 useMemo vs useCallback
目录
- 一、介绍
- `useMemo` 与 `useCallback` 的区别
- 示例代码
- `useMemo` 示例
- `useCallback` 示例
- 总结
- 二、当一个函数被作为依赖项
- `useMemo` 和 `useCallback` 的适用情况
- 选择使用 `useCallback` 或 `useMemo`
- 总结
- 实际例子
一、介绍
在 React 中,useMemo 和 useCallback 是两个用于性能优化的钩子,尽管它们有些相似,但各自有不同的用途和应用场景。理解它们的区别和适用情况可以帮助你更有效地管理组件的性能和状态。
useMemo 与 useCallback 的区别
-
useMemo:- 目的: 用于记忆化(缓存)计算结果。它接受一个计算函数和依赖项数组,只有当依赖项发生变化时,计算函数才会重新执行。
- 用法: 当你需要避免在每次渲染时重复计算一个值时使用。比如,当计算一个复杂的值(如列表过滤、排序)时,可以使用
useMemo来缓存计算结果,避免不必要的重新计算。 - 语法:
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
-
useCallback:- 目的: 用于记忆化(缓存)函数。它接受一个函数和依赖项数组,只有当依赖项发生变化时,函数才会重新创建。
- 用法: 当你需要避免在每次渲染时重新创建一个函数,尤其是当函数作为 props 传递给子组件时,使用
useCallback可以确保子组件不因函数的重新创建而重新渲染。 - 语法:
const memoizedCallback = useCallback(() => {// Your callback logic }, [dependencies]);
示例代码
useMemo 示例
假设你有一个计算密集型的函数 computeExpensiveValue,它依赖于 a 和 b。
import React, { useMemo, useState } from 'react';const ExpensiveComponent = ({ a, b }) => {// 使用 useMemo 缓存计算结果const result = useMemo(() => computeExpensiveValue(a, b), [a, b]);return <div>{result}</div>;
};function computeExpensiveValue(a, b) {// 假设这个函数很复杂console.log('Computing expensive value...');return a + b;
}
在这个示例中,computeExpensiveValue 只会在 a 或 b 改变时重新计算,否则会返回缓存的结果。
useCallback 示例
假设你有一个处理点击事件的函数 handleClick,它被传递给子组件 ButtonComponent。
import React, { useCallback, useState } from 'react';const ParentComponent = () => {const [count, setCount] = useState(0);// 使用 useCallback 缓存函数const handleClick = useCallback(() => {setCount(count + 1);}, [count]);return <ButtonComponent onClick={handleClick} />;
};const ButtonComponent = ({ onClick }) => {console.log('ButtonComponent rendered');return <button onClick={onClick}>Click me</button>;
};
在这个示例中,handleClick 只会在 count 改变时重新创建,从而避免不必要的子组件重新渲染。
总结
useMemo: 用于缓存计算结果。适用于复杂计算、渲染时计算。useCallback: 用于缓存函数。适用于避免函数重新创建,尤其是当函数作为 props 传递给子组件时。
选择使用 useMemo 还是 useCallback 取决于你的具体需求。如果你需要记忆化计算结果,使用 useMemo;如果你需要记忆化函数,使用 useCallback。通常,它们可以结合使用,以优化性能和避免不必要的渲染或计算。
二、当一个函数被作为依赖项
当你有一个函数被用作依赖项时,是否应该使用 useMemo 还是 useCallback 来封装它,取决于你的具体情况。下面是关于这两种钩子的详细指南,以帮助你做出决定:
useMemo 和 useCallback 的适用情况
-
useCallback:-
用途: 用于缓存函数的实例。它创建一个稳定的函数引用,只有当其依赖项发生变化时,才会重新创建该函数。
-
使用场景:
- 当你需要将函数传递给子组件作为
props,以避免子组件因为函数引用变化而重新渲染。 - 当你需要确保函数在依赖项变化时保持稳定。
- 当你需要将函数传递给子组件作为
-
示例:
import React, { useCallback, useState } from 'react';const ParentComponent = () => {const [count, setCount] = useState(0);// 使用 useCallback 缓存函数const handleClick = useCallback(() => {setCount(count + 1);}, [count]); // 依赖项为 countreturn <ChildComponent onClick={handleClick} />; };const ChildComponent = ({ onClick }) => {console.log('ChildComponent rendered');return <button onClick={onClick}>Click me</button>; };
-
-
useMemo:-
用途: 用于缓存计算结果。它记忆化计算结果,只有在依赖项发生变化时,才会重新计算。
-
使用场景:
- 当你有一个计算密集型的操作,且希望避免每次渲染都进行重复计算。
- 当你需要缓存某个值而不是函数,以减少计算量。
-
示例:
import React, { useMemo, useState } from 'react';const ParentComponent = ({ items }) => {// 使用 useMemo 缓存计算结果const sortedItems = useMemo(() => {return [...items].sort(); // 假设这是一个耗时的排序操作}, [items]); // 依赖项为 itemsreturn <ChildComponent items={sortedItems} />; };const ChildComponent = ({ items }) => {return (<ul>{items.map((item, index) => (<li key={index}>{item}</li>))}</ul>); };
-
选择使用 useCallback 或 useMemo
-
函数作为依赖项: 如果你有一个函数作为依赖项,并且你希望这个函数的引用在组件的生命周期中保持稳定,使用
useCallback是合适的。例如,如果你将这个函数作为props传递给子组件,useCallback可以确保子组件不会因为函数引用的变化而重新渲染。 -
计算结果作为依赖项: 如果你希望缓存一个值的计算结果,而这个值的计算依赖于某些状态或属性,使用
useMemo是合适的。例如,如果你有一个计算密集型的值需要在依赖项变化时重新计算,但希望在依赖项没有变化时返回缓存的结果。
总结
- 使用
useCallback: 当你需要稳定的函数引用,尤其是当这个函数作为依赖项或传递给子组件时。 - 使用
useMemo: 当你需要缓存计算结果,以避免重复的计算操作。
实际例子
假设你有一个函数 fetchData 被用作依赖项,在 useEffect 中:
import React, { useEffect, useCallback } from 'react';const MyComponent = ({ fetchData }) => {// 假设你在 useEffect 中使用 fetchDatauseEffect(() => {fetchData(); // 只在 fetchData 变化时调用}, [fetchData]);// 使用 useCallback 缓存 fetchData(如果需要稳定性)const memoizedFetchData = useCallback(fetchData, [fetchData]);return <div>Content</div>;
};export default MyComponent;
在这个例子中,useCallback 用于确保 fetchData 函数的稳定引用。如果 fetchData 是从 props 中传递进来的,你可以使用 useCallback 来缓存它的引用。
总的来说,选择 useMemo 还是 useCallback 取决于你是否在意函数的稳定性还是计算结果的稳定性。
相关文章:
WHAT - React 函数与 useMemo vs useCallback
目录 一、介绍useMemo 与 useCallback 的区别示例代码useMemo 示例useCallback 示例 总结 二、当一个函数被作为依赖项useMemo 和 useCallback 的适用情况选择使用 useCallback 或 useMemo总结实际例子 一、介绍 在 React 中,useMemo 和 useCallback 是两个用于性能…...
系统分析师7:数学与经济管理
文章目录 1 图论应用1.1 最小生成树1.2 最短路径1.3 网络与最大流量 2 运筹方法2.1 线性规划2.2 动态规划2.2.1 供需平衡问题2.2.2 任务指派问题 3 预测与决策3.1 不确定型决策分析3.2 风险型决策3.2.1 决策树3.2.2 决策表 4 随机函数5 数学建模 1 图论应用 ①最小生成树 连接…...
一套简约的qt 蓝色qss方案
一套简约的qt 蓝色qss方案 直接使用qss代码 QMenu {background: qlineargradient(x1:0, y1:0, x2:0, y2:1,stop:0 rgba(255, 255, 255, 240),stop:0.2 rgba(255, 255, 255, 200),stop:0.6 rgba(255, 255, 255, 160),stop:1 rgba(255, 255, 255, 120));qproperty-effect: blur…...
OCSP原理及实践
1.OCSP介绍 在PKI体系中,CA机构颁发合法的证书。使用者可以使用CA根证书验证该证书是否被篡改过,但无法从证书文件验证出证书是否被吊销。因此CA机构会通过发布CRL(Certificate Revocation List)来告知所有人,哪些证书…...
前端流程图框架
1、Mermaid: Mermaid 是一个用于绘制流程图、时序图、甘特图等的纯 JavaScript 库。它使用简单的文本语法来定义图表结构,支持多种类型的流程图,易于集成到网页中。 2、Draw.io: Draw.io 是一个在线的流程图绘制工具࿰…...
13.6 编写go代码接收webhook的告警发送钉钉
本节重点介绍 : 使用钉钉机器人发送到钉钉群通过alertmanager webhook发送我们自定义的go程序中解析alert对象并拼接钉钉信息发送 需求分析 使用钉钉机器人发送到钉钉群 钉钉机器人发送群消息 文档地址 通过webhook发送我们自定义的go程序中 然后解析发过来的alert&#x…...
codetest
1、寻找身高相近的小朋友 #include <iostream> #include <bits/stdc.h>using namespace std;//寻找身高相近的小朋友//输入,第一行两个整数,分别是小明身高,其他小伙伴个数,第二行是其他小伙伴的身高 //100 10 //95 …...
MyBatis-Plus拦截器接口InnerInterceptor失效?因MyBatis缓存机制而踩的一个深坑
InnerInterceptor 接口是 MyBatis-Plus 提供的一个拦截器接口,用于实现一些常用的 SQL 处理逻辑。例如某个组件运作在多系统的平台上,不同系统需要隔离,于是可以通过这个拦截器接口,给每一条要执行的sql末尾拼接一个AND systemId …...
jmeter之计数器
计数器作用: 对于自增长的数字,可以使用计数器实现 一、添加计数器及参数说明 添加计数器 计数器参数说明 Starting value:给定计数器的起始值、初始值,第一次迭代时,会把该值赋给计数器 递增:每次迭代…...
协议集合(学习笔记)
按照数据的传送方式,通信协议可分为以下2种。 串行通信:串行(Serial)指的是逐个传输数据位,一次只传输一个位。 并行通信:并行(Parallel)指的是同时传输多个数据位,一次…...
进程
进程 进程进程的含义PCB块内存空间进程分类:进程的作用进程的状态进程已经准备好执行,所有的资源都已分配,只等待CPU时间进程的调度 进程相关命6.查询进程相关命令1.ps aux2.top3.kill和killall发送一个信号 函数1.fork();2.getpid3.getppid示…...
10款好用的电脑监控软件推荐丨2024年干货整理,赶紧码住!
选择合适的电脑监控软件可以帮助企业和个人更好地管理和保护其计算机资源。以下是10款较为好用的电脑监控软件推荐。 1. 安企神 7天试用体验https://work.weixin.qq.com/ca/cawcde06a33907e60a 简介:安企神是一款专为企业设计的信息安全管理软件,提供…...
【MySQL-24】万字全面解析<索引>——【介绍&语法&性能分析&使用规则】
前言 大家好吖,欢迎来到 YY 滴MySQL系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY的《Lin…...
刷题记录(2)
1. HWOD机试 - 模拟消息队列(100) package com.yue.test;import org.junit.Test;import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List;/*** Author: 夜雨* Date: 2021-12-08-10:31* Description:* Version 1.0*/ public…...
JVM中的GC过程
堆内存结构:在详细讨论GC过程之前,需要了解JVM堆内存的结构。JVM堆内存通常被分为新生代(Young Generation)和老年代(Old Generation),其中新生代又进一步细分为Eden区(Eden Space&a…...
Python实战项目:天气数据爬取+数据可视化(完整代码)_python爬虫实战
一、选题的背景 随着人们对天气的关注逐渐增加,天气预报数据的获取与可视化成为了当今的热门话题,天气预报我们每天都会关注,天气情况会影响到我们日常的增减衣物、出行安排等。每天的气温、相对湿度、降水量以及风向风速是关注的焦点。通过…...
FFmpeg源码:compute_frame_duration函数分析
一、compute_frame_duration函数的定义 compute_frame_duration函数定义在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的源文件libavformat/demux.c中: /*** Return the frame duration in seconds. Return 0 if not available.*/ stat…...
ARM 异常处理(21)
异常的流程: 首先: 在硬件上阶段: 这里是4大步3小步 然后是 异常处理: 这里主要是保存现场,进行异常处理 然后是 异常返回: 主要指 恢复现场, 再跳转回去。 首先硬件上ÿ…...
我开源了我的新闻网站项目
🎉 前言 暑假时写了一个Web项目,感觉做的还是有模有样的,不仅做了前端,还加了后端并连了数据库。最近也是将它开源了,一来是为了熟悉一下Github流程和Git使用命令,二来也是想和大家分享一下自己的成果&…...
LlamaIndex 使用 RouterOutputAgentWorkflow
LlamaIndex 中提供了一个 RouterOutputAgentWorkflow 功能,可以集成多个 QueryTool,根据用户的输入判断使用那个 QueryEngine,在做查询的时候,可以从不同的数据源进行查询,例如确定的数据从数据库查询,如果…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
