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,在做查询的时候,可以从不同的数据源进行查询,例如确定的数据从数据库查询,如果…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
