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,在做查询的时候,可以从不同的数据源进行查询,例如确定的数据从数据库查询,如果…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
