react Hooks(useEffect)实现原理 - 简单理解

news/2024/7/15 10:13:49 标签: react.js, 前端, 前端框架

useEffect

语法: useEffect(setup, dependencies?)
含义: useEffect 是一个 React Hook,它允许你 将组件与外部系统同步。

useEffect 源码简单理解

一、mountEffect 和 upadateEffect

useEffect 与其它 hooks 一样分为 mountEffect 和 upadateEffect 两个阶段

第一次执行 mountEffect
在这里插入图片描述
后面执行 upadateEffect
在这里插入图片描述
从代码中可以看出 mountEffect 和 upadateEffect 传参都是 函数 和 依赖数组,调用 mountEffectImplupdateEffectImpl
mountEffectImpl 和 updateEffectImpl 它们的四个入参一样。其中前面两个入参表示 tag 实现了指定的行为,具体可参考源码 ReactSideEffectTags.js 和 ReactHookEffectTags.js文件,暂时忽略。

二、mountEffectImpl 和 updateEffectImpl

mountEffectImpl

在这里插入图片描述
以上代码中可以看出 执行 pushEffect 并将返回结果记录在 hook的memoizedState上

updateEffectImpl

在这里插入图片描述
以下代码可以看出 当 currentHook 为空的时候,updateEffectImpl 的逻辑与 mountEffectImpl 的逻辑是一样。当 currentHook 不为空、依赖数组不为空时,判断依赖数组里的值是否有变化,若相等无变化则执行pushEffect。猜测这个时候的 hookFlags 指不执行这次 useEffect。

不管哪个阶段最终都执行 pushEffect 函数,那它是啥呢?

pushEffect

在这里插入图片描述
这个函数首先根据入参声明了一个新的 effect 并返回。它实际是一个循环链表

Effect = {
  tag: HookEffectTag, // 一个二进制数,它将决定 effect 的行为
  create: () => (() => void) | void, // 绘制后应该运行的回调
  inst: (() => void) | void, // 用于确定是否应销毁和重新创建 effect
  deps: Array<mixed> | null, // 决定重绘制后是否执行的 deps
  next: Effect, // 函数组件中定义的下一个 effect 的引用
};

componentUpdateQueue : 存储 Effect 的全局变量
判断 componentUpdateQueue 是否为空:

  1. componentUpdateQueue 空:与 mountEffect 逻辑类似,它会创建一个空的 componentUpdateQueue,它其实是 {lastEffect: null},之后将 componentUpdateQueue.lastEffect 指向 effect.next,其实就是存了一下 effect
  2. componentUpdateQueue 不为空:
    2.1 lastEffect 为空:这种情况是新的渲染阶段的第一个 useEffect,逻辑处理和 componentUpdateQueue 为空时一致
    2.2 lastEffect 不为空:这种情况意味着这个组件有多个 useEffect,是第二个及其之后的 useEffect 会走到的分支,将 lastEffect 指向下一个 effect

最后 returen effect

小结

以上就是 useEffect 源码的大致流程。表面上到这里就结束啦。
但不难发现,useEffect 的很多功能在上面代码并没有实现。还有以上代码中的 pushEffect 之后又有哪些逻辑呢?componentUpdateQueue 存储 Effect 之后会在哪里被用到?

饿了,先干饭去,后面接着总结。未完待续。。。


http://www.niftyadmin.cn/n/5260197.html

相关文章

详解 AWS Elastic Load Balancing:深入理解配置与优化

负载均衡主要有三种 ALB NLB CAB 其中最常见的就是ALB &#xff08;应用&#xff09;和 NLB&#xff08;网络&#xff09; 由于ALB能够在应用访问层 第七层 也就是 HTTP/HTTPS 进行智能均衡负载 NLB在第四层 TCP/IP 层 进行负载均衡&#xff0c;更关注于传输速度和延迟。 其中…

Ubuntu安装向日葵【远程控制】

文章目录 引言下载向日葵安装向日葵运行向日葵卸载向日葵参考资料 引言 向日葵是一款非常好用的远程控制软件。这一篇博文介绍了如何在 Ubuntu Linux系统 中安装贝瑞向日葵。&#x1f3c3;&#x1f4a5;&#x1f4a5;&#x1f4a5;❗️ 下载向日葵 向日葵官网: https://sunl…

【Qt】报错error:undefined reference to `vtable for Consumer‘的解决方法

1. 问题原因 在创建完程序后&#xff0c;点击构建&#xff0c;显示编译错误。 错误问题如下: error: undefined reference to vtable在编译输出中查看显示如下&#xff1a; error:undefined reference to vtable for custom2. 原因分析 这个错误通常是因为 C 的虚函数表&am…

Linux--RedHat--安装和配置C++环境

百度下载&#xff0c;安装包&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1IgBfCCRxGYZ_PPiedad0xQ 提取码&#xff1a;ffff 下载后&#xff0c;建个目录&#xff0c;先解压好安装包&#xff01; &#xff08;两种方法&#xff09;执行如下命令&#xff1a; 参考…

使用FluentAvalonia组件库快速完成Avalonia前端开发

前言 工欲善其事必先利其器,前面我们花了几篇文章介绍了Avalonia框架以及如何在Avalonia框架下面使用PrismAvalonia完成MVV模式的开发。今天我们将介绍一款重磅级的Avalonia前端组件库,里面封装了我们开发中常用的组件,这样就不用我们自己再写组件了。专注业务功能开发,提…

消息中间件比较

那都有哪些中间件可供选择呢。其实现在主流的消息中间件就4种&#xff1a;kafka、ActiveMQ、RocketMQ、RabbitMQ 下面我们来看一下&#xff0c;他们之间有什么区别&#xff0c;他们分别应该用于什么场景 ActiveMQ 我们先看ActiveMQ。其实一般早些的项目需要引入消息中间件&…

接口优化思路 - 接口防抖

接口防抖 文章目录 接口防抖前言什么是接口防抖&#xff1f; 一、哪些接口需要防抖1. 用户输入类接口2. 按钮点击类接口3. 滚动加载类接口 二、如何确定接口是重复的三、分布式如何做接口防抖1. 使用共享缓存2. 使用分布式锁 四、代码实现1. 请求锁2. 生成唯一key3. 重复提交判…

《PySpark大数据分析实战》-06.安装环境准备

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…