useCallback和forwardRef的联合使用
文章目录
- 一、useCallback
- 二、forwardRef
总结了useCallback、forwardRef中的deps,以及操作子组建时会遇到数据流不同步的问题
一、useCallback
- useCallback可以缓存函数,这样避免组建更新导致的函数重建;
- useCallback在函数更新以后会在deps中对比每一项,有值的变化,会更新函数中依赖项的最新值,重新创建函数;
- 如果没有触发
deps
,那么这个函数不会重新创建,并且函数内使用的state值也不会变化(尤其是累加,赋值);- 但是useRef变量永远是最新值,一般不需要去依赖useRef值,除非他的值变化了需要去刷新函数
- 没有deps,如果只是使用setState消息队列如:
setCount((count) => count + 1)
,则可以拿到最值,但是也只是在函数内部使用;set函数外部依旧不会拿到最新值- 函数也拥有地址,会被deps捕获识别;useCallback可以缓存函数,即函数地址不会更改
import { Col, message, Row, Space } from "antd";
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";export default function ParentRef() {const countRef = useRef(0);const [count, setCount] = useState(0);const [name, setName] = useState(0);// 每一次组建更新,都会生成新的函数,addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc = () => {setCount(count + 1);countRef.current = countRef.current + 1;};// useCallback 中的 deps 变化,才会触发重新生成新的函数;// 没有触发deps更新,也可以调用,但是其中的依赖项使用之前的快照值(set队列函数会显示正常)const handleClick = useCallback(() => {setCount(count + 1); // 引发组件更新countRef.current = countRef.current + 1; // 不会引发组件更新;值的对比// deps 数值或者引用地址的变化,都会触发重新调用生成新的handle}, [countRef.current]);return (<div><p>Parent</p><button onClick={handleClick}>Focus Input</button><hr /></div>);
}
二、forwardRef
- forwardRef控制子组建,useImperativeHandle暴露子组建属性;在页面代码拆分以后,组件逻辑分布分散,使用forwardRef可以快速操作子组建完成动作,而避开了传参的麻烦;
- useImperativeHandle也有deps依赖,类似于useCallback的deps,只有deps依赖变化,才会重新创建createHandle,并更新函数内部的依赖项
- 父组件修改state(类似异步),并且调用子组建init(类似同步),这个时候是来不及更新init中的依赖的,调用时使用了旧值;所以同步调用子组建init会拿到实时值,但是很有可能你希望获取最新值,
一种解决方式是在init参数传入最新值,一种解决方式是子组建监听值的变化,调用对应的函数
- 控制子组建init会避开数据流,导致在数据流变化之前就触发函数,需要注意init函数和最新的数据流的关系
- 注意子组建中 await delay(0),然后setCount(count + 1);点击两次发现打印001122…,
第一次点击:打印函数体内count = 0, delay(0) => (deps变化) => 更新函数体内count = 0(此时setCount还没有值更新)=>count = 1(实际值count);
第二次点击:打印函数体内count = 0,delay(0)=> (deps变化) => 更新函数体内count = 1(实际值count)=>count = 1(实际值count);
第三次点击:才会打印count为1
import { Col, message, Row, Space } from "antd";
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export function ChildRefTemp(props, ref) {const inputRef = useRef(null);const [count, setCount] = useState(0);const [age, setAge] = useState(0);const handleClick = () => {inputRef.current.focus();};const countAdd = async () => {// await delay(0);// 当设置延迟,props.count先让createHandle更新,这个时候count还没有更新,还是旧值展示;// 除了第一次点击,其他时候点击两次才可以让count + 1setCount(count + 1);};// useImperativeHandle: (ref, createHandle, deps)useImperativeHandle(ref,() => {console.log("ChildRefTemp useImperativeHandle"); // 初始化也会调用一次return {init(initCount) {inputRef.current.focus();countAdd();message.success("init" + count);message.success("init props.countRef: " + props.countRef);message.success("init initCount: " + initCount);}};},// 这里的deps依赖,会导致重新调用 createHandle;如果没有依赖,获取值的时候得不到最新值// [age] 不会导致重新调用 createHandle 生成新的handle// 父组件只设置props.countRef,不去setCount,不会导致子组建接收到最新的props.countRef;// 父组件setCount,子组件接收到最新的props.count,导致子组件并没有重新渲染,只要这里的值判断改变,createHandle 中就可以重新最新的数据[props.countRef]);return (<div><input type="text" ref={inputRef} /><button onClick={handleClick}>Focus Input</button><Row style={{ marginTop: 10 }}><Col><Space><span style={{ color: "red" }}>ParentRefcount: {props.count}</span><span style={{ color: "red" }}>ParentRef countRef: {props.countRef}</span><span>count: {count}</span></Space></Col></Row></div>);
}
// forwardRef: (component, props) => ref => component(props, ref)
const ChildRef = forwardRef(ChildRefTemp);export default function ParentRef() {const childRef = useRef(null);const countRef = useRef(0);const [count, setCount] = useState(0);const [name, setName] = useState(0);// 每一次组建更新,都会生成新的函数,addFunc在其他hooks都deps中都会被识别成值产生变化const addFunc = () => {setCount(count + 1);countRef.current = countRef.current + 1;childRef.current.init();};// useCallback 中的 deps 变化,才会触发重新生成新的函数;// 没有触发deps更新,也可以调用,但是其中的依赖项使用之前的快照值(set队列函数会显示正常)const handleClick = useCallback(() => {setCount(count + 1); // 引发组件更新// setCount((count) => count + 1); // 消息队列countRef.current = countRef.current + 1; // 不会引发组件更新;值的对比childRef.current.init(countRef.current);// message.success("handleClick" + count);// deps 数值或者引用地址的变化,都会触发重新调用生成新的handle}, [countRef.current]);return (<div><p>Parent</p><button onClick={handleClick}>Focus Input</button><hr /><p>ChildRef</p>// handleClick 函数也拥有地址,会被deps捕获识别;useCallback可以缓存函数,即函数地址不会更改<ChildRef ref={childRef} count={count} countRef={countRef.current} name={name} handleClick={handleClick} /></div>);
}
相关文章:
useCallback和forwardRef的联合使用
文章目录 一、useCallback二、forwardRef 总结了useCallback、forwardRef中的deps,以及操作子组建时会遇到数据流不同步的问题 一、useCallback useCallback可以缓存函数,这样避免组建更新导致的函数重建;useCallback在函数更新以后会在deps中…...
C# .NET CORE 开发问题汇总
1. error MSB4803: .NET Core 版本的 MSBuild 不支持“ResolveComReference”。请使用 .NET Framework 版本的 MSBuild。 引用了一个COM组件, 使用donet 命令时,提示不支持, 可以先将项目设置为x86以构建, 将COM引用添加到核心项目中,构建它,在obj\x86\…...
【C语言】拆数字组成最大数
相信你是最棒哒!!! 文章目录 题目描述 正确代码 法一注释版 简洁版 法二注释版 简洁版 题目描述 任意输入一个自然数,输出该自然数的各位数字组成的最大数。例如,输入 1593 ,则输出为 9531 。 输入描述 …...
【Git系列】根据提交打印邮箱
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理
Nginx在处理客户端请求的并发性发面是否依赖Linux的多线程原理 Nginx 在处理客户端请求的并发性方面,并不依赖于 Linux 的多线程原理。 Nginx 的并发处理主要基于 事件驱动模型 和 异步非阻塞 I/O,而不是传统的多线程或多进程模型。 Nginx 的并发处理模…...
Python生成对抗神经网络GAN预测股票及LSTMs、ARIMA对比分析ETF金融时间序列可视化
全文链接:https://tecdat.cn/?p38528 本文聚焦于利用生成对抗网络(GANs)进行金融时间序列的概率预测。介绍了一种新颖的基于经济学驱动的生成器损失函数,使 GANs 更适用于分类任务并置于监督学习环境中,能给出价格回…...
深入了解C++中const的用法
文章目录 一、C中的const如何理解?二、C中的const与C语言中的const有何区别?三、const与指针、引用的结合使用 一、C中的const如何理解? 在C中,const是一个关键字,用来表示常量性,意在告诉编译器某些变量或…...
【Linux金典面试题(上)】41道Linux金典面试问题+详细解答,包含基本操作、系统维护、网络配置、脚本编程等问题。
大家好,我是摇光~,用大白话讲解所有你难懂的知识点 之前写了一篇关于 python 的面试题,感觉大家都很需要,所以打算出一个面试专栏。 【数据分析岗】Python金典面试题 这个专栏主要针对面试大数据岗位、数据分析岗位、数据运维等…...
利用Python实现多元回归预测汽车价格
引言: AI技术的热门使得大家对机器学习有了更多的关注,作为与AI技术息息相关的一门课程,从头了解基础的机器学习算法就显得十分有必要,如:梯度下降,线性回归等。 正文: 本文将讲解线性回归中多元回回归的案例 机器学习大致可以分为监督学习,非监督学习、半监督学习还…...
抓包软件fiddler和wireshark使用手册
fiddler官方文档 Fiddler 抓包教程1 Fiddler 抓包教程2 wireshark抓包学习 2添加链接描述 ip 过滤 ip.src_host ip.dst_host ip.addr mac 过滤 eth.src eth.dst eth.addr 端口过滤 tcp.port tcp.srcport tcp.dstport 协议类型过滤 arp dhcp 规则组合 and or...
初识三大 Observer
文章目录 ResizeObserver、MutationObserver和IntersectionObserver用MutationObserver实现图片懒加载MutationObserver 兼容性问题IntersectionObserver 应用MutationObserver和IntersectionObserver的区别IntersectionObserver 实例示例一:图片懒加载示例二&#…...
Eclipse MAT(Memory Analyzer Tool) 使用手册
参考:JAVA内存泄露使用MAT(Memory Analyzer Tool)快速定位代码 Eclipse MAT 1.15.0提示JDK版本最低需要使用17版本的,如果不想安装可以下载ZIP包,或者使用较低版本的MAT。 为了避免下载的17版本JDK和本地环境干扰,可以直接在MAT配…...
TongWe7.0-东方通TongWeb控制台无法访问 排查
**问题描述:**无法访问TongWeb的控制台 逐项排查: 1、控制台访问地址是否正确:http://IP:9060/console #IP是服务器的实际IP地址 2、确认TongWeb进程是否存在,执行命令:ps -ef|grep tongweb 3、确认TongWeb服务启动…...
Ariba Procurement: Administration_Master data
采购主数据集成Procurement Master Data Integration 注意:并非所有元素都是必需的,数据元素的名称可能根据ERP的不同,有所不同。 Types of Master Data Accounting 在SAP Ariba中的各种会计元素字段中,填充有效值选择列表。建…...
爬虫学习案例4
爬取猪八戒网站数据:2024-12-12 使用xpath解析元素,安装依赖库 pip install lxml使用selenium步骤我的上篇博客有提到,这里就不重复了 selenium使用博客导航 # 安装pip install lxml,使用xpath from lxml import etree import time from s…...
Angular模块化应用构建详解
文章目录 前言一、理解Angular模块(NgModule)二、创建功能模块三、懒加载模块以提高性能四、共享模块五、库模块六、最佳实践与注意事项七、案例研究:重构电子商务平台结语 前言 Angular是一款由Google支持的、用于构建动态Web应用程序的前端…...
51c大模型~合集89
我自己的原文哦~ https://blog.51cto.com/whaosoft/12815167 #OpenAI很会营销 而号称超强AI营销的灵感岛实测成效如何? OpenAI 是懂营销的,连续 12 天发布,每天一个新花样,如今刚过一半,热度依旧不减。 毫无疑问&…...
【蓝桥杯备战】Day 1
1.基础题目 LCR 018.验证回文串 给定一个字符串 s ,验证 s 是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。 本题中,将空字符串定义为有效的 回文串 。 示例 1: 输入: s "A man, a plan, a canal: Panama…...
FedAdam算法:供给方信用,数据质量;更新一致性
FedAdam算法:供给方信用,数据质量;更新一致性 FedAdam算法概述 FedAdam是一种联邦学习(Federated Learning)算法。联邦学习是一种机器学习技术,它允许在多个设备或数据中心(称为客户端)上训练模型,而无需将数据集中到一个中央服务器,从而保护数据隐私。FedAdam主要用于…...
内存卡格式化后的数据恢复全攻略
一、内存卡格式化简述 内存卡,作为现代电子设备中不可或缺的存储媒介,广泛应用于手机、相机、行车记录仪等各类设备中。然而,在使用过程中,我们可能会遇到内存卡需要格式化的情况。格式化是一种将内存卡上的所有数据和文件系统清…...
介绍交叉熵损失(Cross-Entropy Loss)以及交叉熵在对比学习中的应用:中英双语
中文版 本文解释 交叉熵损失(Cross-Entropy Loss),并结合对比学习的应用说明它如何工作,以及如何让正样本对更近、负样本对更远。 什么是交叉熵损失? 交叉熵损失是机器学习中常用的一种损失函数,主要用于…...
RabbitMQ的几个概念
注:这篇文章会随时添加新的内容,就是将RabbtiMQ中的概念添加到这里。助力大家的学习 自动ACK和手动ACK的区别 自动ACK和手动ACK是消息队列中两种不同的消息确认机制,它们在消息处理的可靠性和灵活性方面存在显著差异。 自动ACK(…...
Ollama部署大模型并安装WebUi
Ollama用于在本地运行和部署大型语言模型(LLMs)的工具,可以非常方便的部署本地大模型 安装 Linux curl -fsSL https://ollama.com/install.sh | sh我是ubuntu系统安装,其他系统可以看项目的开源地址有写 GitHub - ollama/ollama: Get up and running with Llama 3, Mist…...
Debedium如何忽略Oracle的purge命令
报错 截至目前3.0版本,Debezium的Oracle Connector并不支持purge table这个指令。 所以,在使用Debezium解析Oracle变更的时候,如果在源端执行了类似 purge table "$BIN… 的语句,就会导致Debezium罢工,日志里显…...
PlantUML 语言
PlantUML 是一种开源工具,用于通过简单的文本描述生成 UML 图。它支持多种 UML 图类型,如类图、序列图、用例图、活动图、组件图、状态图等。PlantUML 语言非常简洁,采用类似编程语言的语法,允许用户使用文本定义模型,…...
linux的 .so和.ko文件分别是什么?主要区别是什么?
前言: .so和.ko文件的主要区别在于它们的应用层次和功能不同。 应用层次 .so文件:这是用户层的动态链接库(Shared Object),主要用于用户态的程序中。 它用于动态链接,多个程序可以共享同一个库文件&…...
XX服务器上的npm不知道咋突然坏了
收到同事的V,说是:182上的npm不知道咋突然坏了,查到这里了,不敢动了。 咱一定要抓重点:突然坏了。这里的突然肯定不是瞬间(大概率是上次可用,这次不可用,中间间隔了多长时间&#x…...
数据结构(优先级队列 :Priority Queue)
前言: 在计算机科学中,队列是一种非常常见的数据结构,它遵循先进先出(FIFO)的原则,也就是说,先进入队列的元素会先被处理。然而,在许多实际应用中,我们不仅仅需要按顺序…...
nginx.conf 请求时间部分参数说明新手教程
下面来说下nginx.conf 的部分参数,配置如下: http {include mime.types;default_type application/octet-stream;client_max_body_size 1000M;#log_format main $remote_addr - $remote_user [$time_local] "$request" # …...
【Linux-ubuntu通过USB传输程序点亮LED灯】
Linux-ubuntu通过USB传输程序点亮LED灯 一,初始化GPIO配置1.使能时钟2.其他寄存器配置 二,程序编译三,USB传输程序 一,初始化GPIO配置 1.使能时钟 使能就是一个控制信号,用于决定时钟信号是否能够有效的传递或者被使用,就像一个…...
用ps做网站方法/百度销售平台
2019独角兽企业重金招聘Python工程师标准>>> 概述 很多时候 mysql安装完root用户的默认密码不为空,这时候就需要通过其它办法登入到mysql重置密码。 步骤 方法1:查看/root/.mysql_secret文件 安装mysql第一次会生成一个随机密码,…...
网站如何做地面推广/百度人工客服24小时
300道计算机应用基础试题简化版(附答案)第 PAGE 16 页 共 NUMPAGES 16 页计算机应用基础试题及答案(注: 200道选择,100道填空)一、选择题:1. 在计算机应用中,“计算机辅助设计”的英文缩写为___________。A. CAD 2. 微型计算机中&…...
微3g网站/关键词排名网络推广
[ 用大白话讲解复杂的技术 ]这是我的第41篇原创文章作者 l 会点代码的大叔(CodeDaShu)今天,我们来聊聊 Java 的注解。01注解的概念Annotation(注解):先看看官方给出的概念,注解是 Java 提供的一种对元程序中元素关联信息和元数据的途径和方法…...
分布式加载网站的静态/郑州网络推广效果
一个理想的弹簧振子固定于墙上,来回振动,从室内人看,其机械能守恒, 从一匀速运动火车上看, 弹簧固定点在移动,而且固定点有作用力,因此外力对弹簧振子系统做功不为零, 弹簧的机械能不守恒.类似的另一情景...
和文化有关的吉网站建设模板/海南百度竞价推广
文章目录1. 《ClickHouse和Doris之OLAP谁与争锋》课程介绍1.1. 本次系列课程介绍1.2. 今日课程大纲2. ClickHouse 表引擎详解和架构原理2.1. ClickHouse 设计思想和核心技术特征2.1.1. ClickHouse 全知全解2.1.2. ClickHouse 设计思路剖析2.2. ClickHouse 表引擎详解2.2.1. Cli…...
wordpress微信付款插件/文员短期电脑培训
detail订单详情表字段名 数据类型 默认值 允许非空 自动递增 备注id int(11) NO 是 idorderid int(11) NO 订单id号goodsid int(11) NO 商品id号name varchar(32) NO 商品名称prince double(6,2) NO 单价num int(11) NO 数量orders订单表字段名 数据类型 默认值 允许非空 自动递…...