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

React的useEvent 和 ahooks 的 useMemorizedFn 的深度分析和对比

父组件

const TestParent: React.FC<any> = () => {const [State, setState] = useState(0);const changeFun = useCallback(() => {console.log('useCallback closure 里的  State', State);}, [State]);const changeFun_useEvent = useEvent(() => {console.log('useEvent closure 里的  State', State);});const changeFun_usememrized = useMemorizedFn(() => {console.log('useMemorizedFn closure 里的  State', State);});return (<div style={{ width: '100%', padding: '20px', backgroundColor: 'green' }}>父组件的state: {State}<button onClick={() => setState(Math.random())}>click-change state</button><TestChild changeFun={changeFun_useEvent}></TestChild><TestChild changeFun={changeFun_usememrized}></TestChild></div>);
};

子组件

const TestChild = (props: any) => {const { changeFun } = props;useEffect(() => {console.log('changeFun-》地址change了,导致了子组件刷新了。');}, [changeFun]);return (<div style={{ backgroundColor: 'pink' }}>子组件<br /><br /><button onClick={changeFun}>child click - get parent's state </button></div>);
};
React.memo(TestChild);

useEvent

已被官方废弃

useEvent 源码解析

【解释1】
1、由于每次父组件更新,都会执行到 下面的代码。这个是首要条件!
const changeFun_useEvent = useEvent(() => {
console.log('useEvent closure 里的  State', State);
});

2、其次,每次执行都会传递过来一个新的handler,自然带来了新的闭包、新的数据。

3、最后,useLayoutEffect的作用是每次数据发生更新,自动的去执行里面的方法。

4、 所以 handlerRef.current 就能拿到带着最新数据的一个handler

【解释2】

useCallback 并且依赖为[],只执行一次,地址也就永远不会变了。
那么,useEvent()return出去函数的地址永不变化。

可以解释为

1、useEvent() return 出去了一个对象,为  obj = {A:{}}2、 useCallback里的箭头函数return出去的是这个 fn=handlerRef.current;相当于一个属性 A 由于handlerRef.current指向地址是不停变化的,所以A得指向地址就是不停变化的。3、因此我们真正使用 changeFun_useEvent=useEvent(xx)的时候, 拿到的是obj。永远不变的地址。changeFun_useEvent()调用的时候拿到的就是obj.A了。就是最新的带着最新数据的一个handler
function useEvent(handler: any) {const handlerRef = useRef(null);// In a real implementation, this would run before layout effects// 这行保证handlerRef一直处于,最新的闭包、拿到最新的数据。【解释1】useLayoutEffect(() => {console.log('useLayoutEffect执行了');handlerRef.current = handler;});
//这行保证返回的数据地址永远不变,但是执行的时候拿到的最新的。【解释2】return useCallback((...args: any) => {// In a real implementation, this would throw if called during renderconst fn = handlerRef.current;return fn(...args);}, []);
}
useMemorizedFn源码解析

源码地址
【解释1】
fn在这里做依赖的原因: 由于每次父组件重新执行,都会走到useMemorizedFn里并传过来一个新的箭头函数。所以fn每次地址都是新的。也就带来了新数据的闭包。fnRef.current也就是解释2里的A的地址每次都是新的,带着新的数据的闭包。

【解释2】
这里可以解释为: const obj = {A:{}} ;
memoizedFn.current = obj;
fnRef.current = A
当执行memoizedFn.current的时候也就是去访问并执行了 obj.A

function useMemorizedFn(fn: any) {const fnRef = useRef(fn);// 这行保证fn一直处于,最新的闭包、拿到最新的数据。【解释1】//这里为什么不直接  fnRef.current =  fn  ,可参考官网。总结就是 fnRef.current的需要放到useMemo。否则reactdev tool监听不到变化。fnRef.current = useMemo(() => {console.log('useMemo执行了'); // 父级改变就执行return fn;}, [fn]);const memoizedFn = useRef<any>();// 下面保证fn引用地址不变、且每次都能拿到最新的闭包 【解释2】if (!memoizedFn.current) {memoizedFn.current = function (this: any, ...args: any) {return fnRef.current.apply(this, args);//立即执行、改变this指向、传递参数 3个作用};}return memoizedFn.current;
}
总结

由此我们看出。其实二者的原理和出发点都是一致的,都是返回的是个固定的对象obj,该对象地址不变,但是调用的方法的时候相当于调用了obj.A,此属性的指向是会一直更新的。
只不过更新的时候 :useevent用了useLayoutCallback做更新,useMemorizedFn则使用了useMemo。
保持地址不变的时候:useevent用的是useCallback ,useMemorizedFn使用的一个 !memoizedFn.current + 新固定的function 。

此文纯属个人理解,有偏差望指正。

相关文章:

React的useEvent 和 ahooks 的 useMemorizedFn 的深度分析和对比

父组件 const TestParent: React.FC<any> () > {const [State, setState] useState(0);const changeFun useCallback(() > {console.log(useCallback closure 里的 State, State);}, [State]);const changeFun_useEvent useEvent(() > {console.log(useEv…...

基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统

goframe-admin goframe-admin V1.0.0 平台简介 基于goframe2.5.4、vue3、tdesign-vue-next开发的全栈前后端分离的管理系统。前端采用tdesign-vue-next-starter 、vue3、pinia、tdesign-vue-next。 特征 高生产率&#xff1a;几分钟即可搭建一个后台管理系统认证机制&#x…...

LInux之在同一Tomcat下使用不同的端口号访问不同的项目

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《LInux实战开发》。&#x1f3af;&#x1f3af; …...

梦百合上榜2023鼎革奖数字化转型先锋榜

10月26日,第六届“鼎革奖”数字化转型先锋榜单揭晓,梦百合家居凭借数字化生产的卓越成果——SAP管理平台及供应链项目,入选2023【鼎革奖】数字化转型先锋榜年度供应链转型典范,梦百合家居COO 崔慧明同步入选2023【鼎革奖】数字化转型先锋榜年度首席运营官。 据了解,「鼎革奖」数…...

沉痛悼念科研分公司

今天上班途中&#xff0c;遇到了上家公司的同事王强。他正准备去体检中心体检。几句寒暄之后&#xff0c;得知他是要入职选煤公司了。 我们所在的公司比较大&#xff0c;总公司下设有几十个分、子公司&#xff0c;我和他曾经在一家子公司——科研分公司。现在的科研分公司解散…...

Django的网站项目开发好了,该用何种方案在Centos上部署【答:Gunicorn(uWSGI)+Nginx】

问&#xff1a;用Django开发的网站开发好了&#xff0c;现在要部署上线。 系统为Centos 7.x 现在我安装好Django和相关依赖后&#xff0c;我用命令 python manage.py runserver 127.0.0.1:8010 启动Django 然后安装配置好Nginx,并把用的请求转发到 127.0.0.1:8010 。 请问这样的…...

基于PyTorch的中文情绪分析器设计与开发

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、相关基础理论2.1 主流深度学习框架2.2 神经网络2.2.1 神经网络基础 二、中文情感分类模型构建3.1 开发环境3.2 数据部分3.3 文本特征提取3.3.1、过滤标点符号3.3.2 中文分词、单词过滤 三 运行结果与分析五 结…...

HT5010 音频转换器工作原理

HT5010是一款低成B的立体声DA转换器&#xff0c;内部集成了内插滤波器、DA转换器和输出模拟滤波等电路。其可支持多种音频数字输入格式&#xff0c;支持24-bit字节。 该HT5010 基于一个多比特位的Δ-Σ调制器&#xff0c;将数字信号转化成两个声道的模拟信号并经过模拟滤波器滤…...

ubuntu18.04如何更新到22.04

将linux系统中的Ubuntu 18.04更新到22.04&#xff0c;按照以下步骤操作&#xff1a; 打开终端并更新系统&#xff0c;使用以下命令&#xff1a; sudo apt update sudo apt upgrade sudo apt dist-upgrade 确保系统是最新的&#xff0c;然后备份数据&#xff0c;以防万一。执…...

嵌入式软件开发:第二部分–七个步骤计划

使用一种工具&#xff08;仅一种工具&#xff09;武装自己&#xff0c;您可以在下一个嵌入式项目的质量和交付时间上做出巨大的改进。点击领取嵌入式物联网学习路线 该工具是&#xff1a;绝对承诺对开发代码的方式进行一些小而基本的更改 。 有了改变的意志&#xff0c;今天您…...

什么是IPA,和RPA有啥区别和联系?

∵ IPA中包含了RPA的“PA”&#xff0c;AI的“I” ∴IPARPAAI&#xff0c;等式成立&#xff01; AI&#xff1a;或人工智能&#xff0c;是一种复杂的计算机技术&#xff0c;旨在模仿人类智能行为和决策的能力。它涵盖了多种技术和方法&#xff0c;包括&#xff1a;机器学习&am…...

内涝积水监测仪怎么样?万宾科技城市内涝积水监测的作用

在城市建设发展过程中&#xff0c;道路基础设施的建设永远都占据着重要一席&#xff0c;因为人们出行一旦受阻便会影响城市进展&#xff0c;也会影响经济发展。在城市之中有隧道&#xff0c;下穿式立交桥等容易存积水的地方&#xff0c;一旦出现恶劣暴雨天气&#xff0c;这些地…...

【java】命令行,包

文件夹情况&#xff1a; HelloWorld.java package com.demo; public class HelloWorld{public static void print(){System.out.println("HelloWorld!");}public static void main(String[] args){print();} } import.java import com.demo.HelloWorld; public cla…...

Generative AI 新世界 | 文生图(Text-to-Image)领域论文解读

在上期文章&#xff0c;我们开始探讨生成式 AI&#xff08;Generative AI&#xff09;的另一个进步迅速的领域&#xff1a;文生图&#xff08;Text-to-Image&#xff09;领域。概述了 CLIP、OpenCLIP、扩散模型、DALL-E-2 模型、Stable Diffusion 模型等文生图&#xff08;Text…...

03.从简单的sql开始

从简单的sql开始 一、sql语句的种类二、oracle的工作原理三、oracle数据库常见基础命令 一、sql语句的种类 下面是SQL语句的分类、常用语句、使用方法&#xff1a; 分类语句使用方法解释数据查询SELECTSELECT column1, column2, … FROM table_name WHERE condition;用于从表…...

JS加密/解密之jsjiami在线js加密的效率问题

故事背景 ​ 经常有客户反馈&#xff0c;v7加密的效率比v6低&#xff0c;但是安全性更好。这里我给大家科普一下关于jsjiami的优化诀窍。 示例源代码 // 伪代码 while (1) {var name ‘张三’ }优化后 var _name 张三; while (1) {var name _name }优化原理 相信很多朋…...

解决【spring boot】Process finished with exit code 0的问题

文章目录 1. 复现错误2. 分析错误3. 解决问题 1. 复现错误 今天从https://start.spring.io下载配置好的spring boot项目&#xff1a; 启动后却报出如下错误&#xff1a; 即Process finished with exit code 0 2. 分析错误 Process finished with exit code 0翻译成中文进程已完…...

模电学习路径

交流通路实质 列出电路方程1&#xff0c;方程1对时刻t做微分 所得方程1‘ 即为 交流通路 方程1对时刻t做微分&#xff1a;两个不同时刻的方程1相减&#xff0c;并 令两时刻差为 无穷小 微分 改成 差 模电学习路径&#xff1a; 理论 《电路原理》清华大学 于歆杰 朱桂萍 陆文…...

【Linux】配置JDKTomcat开发环境及MySQL安装和后端项目部署

目录 一、jdk安装配置 1. 传入资源 2. 解压 3. 配置 二、Tomcat安装 1. 解压开启 2. 开放端口 三、MySQL安装 1. 解压安装 2. 登入配置 四、后端部署 1. 数据库 2. 导入.war包 3. 修改端口 4.开启访问 一、jdk安装配置 打开虚拟机 Centos 登入账号&#xff…...

Modelsim 使用教程(3)——Projects

目录 一、概述 二、设计文件及tb 2.1 设计文件 counter.v 2.2 仿真文件 tcounter.v 三、操作流程 3.1 Create a New Project&#xff08;创建一个新的工程&#xff09; 3.2 Add Objects to the Project&#xff08;把代码加入项目&#xff09; 3.3 Compile the …...

嵌入式C语言开发中的三大致命陷阱

很多人刚开始学习C语言时,会觉得: 会指针 会结构体 会寄存器操作 能驱动外设 似乎就已经掌握了嵌入式开发。 但真正进入项目后才会发现: 嵌入式开发最难的,从来不是语法,而是“代码与硬件现实世界之间的耦合”。 同样一句代码: 在PC上可能只是运行错误; 在单片机里却可…...

解析美国RTP导热工程塑料在电子散热领域的性能表现与行业应用

美国RTP导热工程塑料通过填充陶瓷、金属等导热介质提升材料热导率&#xff0c;同时保持优异机械性能与绝缘特性&#xff0c;完美适配电子散热场景。行业数据显示其热导率可达1-20 W/(mK)&#xff0c;远超普通塑料0.2W/(mK)水平&#xff0c;成为解决电子设备过热问题的优选方案。…...

C#与Unity的协作协议:从语法表层到引擎契约的深度解析

1. 这不是“学编程”&#xff0c;而是重新建立你和机器对话的语法系统很多人点开这个标题&#xff0c;心里想的是&#xff1a;“Unity游戏开发&#xff1f;那我得先学会C#&#xff0c;再学Unity编辑器&#xff0c;最后做个小飞机打砖块……”——这个思路本身就把门关死了。我带…...

【反演】基于粒子群算法PSO进行反演附Matlab代码和报告

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、程序设计科研仿真。&#x1f34e;完整代码获取 定制创新 论文复现点击&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1f3…...

投影仪的分辨率不高,仅为1024*768的分辨率,而笔记本电脑2560×1600(2.5K)分辨率。‌‌——如果采用扩展屏复制笔记本电脑分辨率,发现那个投影仪投影出的字很小,且看不清。 将笔记本电脑的

投影仪的分辨率不高,仅为1024*768的分辨率,而笔记本电脑25601600(2.5K)分辨率。‌‌——如果采用扩展屏复制笔记本电脑分辨率,发现那个投影仪投影出的字很小,且看不清。 将笔记本电脑的分辨率也改为1024*768的分辨率,投影仪字体大小会放大才看的清楚,但是软件无法全部显…...

2026 河北 GEO 优化服务商测评:理性看实力,盘古开物AI智推适配才是硬道理

覆盖石家庄、唐山、保定、邯郸、邢台&#xff0c;立足华北&#xff0c;辐射全国&#xff0c;不搞噱头&#xff0c;只讲真实能力随着生成式 AI 全面融入商业营销&#xff0c;GEO 优化已经从河北企业的可选服务&#xff0c;变成抢占区域流量、提升线上可见度的重要方式。尤其制造…...

昇腾CANN的算子“零件厂“:catlass仓库到底在生产什么

如果把昇腾NPU上的大模型算子比作一辆汽车&#xff0c;FlashAttention是发动机&#xff0c;RMSNorm是刹车片&#xff0c;RoPE是方向盘——那catlass是什么&#xff1f;是生产这些零件的模具和机床。 第一次接触昇腾CANN生态的时候&#xff0c;很容易忽略catlass。它不像ops-tr…...

免费德州扑克GTO求解器终极指南:如何用Desktop Postflop提升你的扑克决策能力

免费德州扑克GTO求解器终极指南&#xff1a;如何用Desktop Postflop提升你的扑克决策能力 【免费下载链接】desktop-postflop [Development suspended] Advanced open-source Texas Holdem GTO solver with optimized performance 项目地址: https://gitcode.com/gh_mirrors/…...

Godot RE Tools深度解析:游戏逆向工程的全栈解决方案

Godot RE Tools深度解析&#xff1a;游戏逆向工程的全栈解决方案 【免费下载链接】gdsdecomp Godot reverse engineering tools 项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp 在游戏开发与逆向工程领域&#xff0c;Godot引擎的二进制资源格式一直是一个…...

构建中文AI的未来:MNBVC超大规模语料库的深度解析与实践指南

构建中文AI的未来&#xff1a;MNBVC超大规模语料库的深度解析与实践指南 【免费下载链接】MNBVC MNBVC(Massive Never-ending BT Vast Chinese corpus)超大规模中文语料集。对标chatGPT训练的40T数据。MNBVC数据集不但包括主流文化&#xff0c;也包括各个小众文化甚至火星文的数…...