热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

useEffect和useLayoutEffect的源码解读

文章目录useEffect和useLayoutEffect的源码解读useEffect源码解读mountEffectImplpushEffectupdateEffectImpl疑惑


文章目录


    • useEffect 和 useLayoutEffect 的源码解读
      • useEffect
        • 源码解读
          • mountEffectImpl
            • pushEffect

          • updateEffectImpl
            • 疑惑:



      • useLayOutEffect
        • 源码解读
          • mountLayoutEffect
          • updateLayoutEffect

        • 总结






useEffect 和 useLayoutEffect 的源码解读


useEffect

文件在 packages/react-reconciler/src/ReactFiberHooks.old.js


源码解读

在这里插入图片描述
在这里插入图片描述

根据上一篇 useState 的经验可知,useEffect 在 mount 的时候,会调用 mountEffectImpl 函数,在 update 的时候,会调用 updateEffectImpl 函数

在这里插入图片描述


mountEffectImpl

  1. 首先调用 mountWorkInProgressHook 获取当前 hook对应的数据

  2. 获取 effect 对应的 依赖项

  3. 为当前 fiber 的 flags 增加上 该hook的 fiberFlags(这个 fiberFlags 对于 useEffect 和 useLauoutEffect 是不同的,所以用于区分这两者)

  4. 将pushEffect函数返回的 新的 effect 赋值给 hook.memoizedState

    (注意:对于 useState 来说,memoizedState 保存的是状态,而 useEffect 来说,memoizedState 实际上是保存的 当前hook上最后一个 effect 数据)

在这里插入图片描述


pushEffect

判断 componentUpdateQueue 是否存在,若存在,就为这个环状链表附加一个 effect;若不存在,就新建一个环状链表


  1. 首先会创建一个变量 componentUpdateQueue,并被赋值给 currentlyRenderingFiber.updateQueue

    updateQueue 的数据结构是:

  2. 若 componentUpdateQueue 不存在,把创建的数据结构 effect 挂载到 componentUpdateQueue.lastEffect 上,并且effect 与自己形成一条环状链表(与 update 的时候,数据结构类似)

  3. effect数据结构:(结合 useEffect 的API,判断以下)


    1. create :是 useEfect 的回调函数
    2. destroy:useEfect 的回调函数的返回值的 那个函数
  4. 若 componentUpdateQueue 存在,则在环状链表后面新加上一个 effect

  5. 最终返回本次创建的 effect

在这里插入图片描述


updateEffectImpl

useEffect 在 mount 和 update 阶段有什么区别吗?

在 update时,前一个 useEffect 已经被执行过了,所以说前一个 useEffect 可能存在他的 destory 函数


  1. 从currentHook.memoizedState中取出 上一次 更新的 effect,即 prevEffect
  2. 再从 prevEffect 中取出 destory 函数(注意:需要上一次 effect 中的 create 执行完之后 ,才会有 上一次 effect 的 destory 函数)
  3. 判断 上一次的 deps 和 这一次的 deps 比较是否相等:不论是否相等,都会pushEffect,只是区别在于一个 hookHasEffect 参数。若相等,在 pushEffect 函数的第一个参数是直接传一个 hookFlags 参数,若不相等,是传的 HookHasEffect | hookFlags

疑惑:

为什么要在 deps 没有改变的情况下,还要 pushEffect 呢?

解答:

在 函数组件中,所有 hook 是保存在 fiber.memoizedState 上,并且会形成一个单向的环状链表,这些 hooks 的调用顺序都是不变的,同样,对于 useEffect 和 useLayoutEffect,也是保存在一条单向链表上的,顺序也不能改变。所以即使本次更新 deps 没有改变,不会调用 hooks 对应的回调函数,我们也需要 pushEffect,确保hooks的环状链表在整个更新中都是能对应的上的

在这里插入图片描述


useLayOutEffect


源码解读

在 mount 阶段时,调用 mountLayoutEffect 函数,在 update 阶段时,调用 updateLayoutEffect


mountLayoutEffect

可以看出 mountLayoutEffect 最终也是调用 mountEffectImpl 函数,只不过 传入的第二个参数是 HookLayout
在这里插入图片描述


updateLayoutEffect

和 mountLayoutEffect 同理,也是调用的 updateEffectImpl, 传入的第二个参数是 HookLayout

在这里插入图片描述


总结

所以 useEffect 和 useLayoutEffect 他的整体运行流程基本一致,唯一不同的是 在 commit 阶段会在不同的时机 调用







推荐阅读
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • RingBuffer,或者说CircularBuffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • Question该提问来源于开源项目:react-native-device-info/react-native-device-info ... [详细]
  • java线程池的实现原理源码分析
    这篇文章主要介绍“java线程池的实现原理源码分析”,在日常操作中,相信很多人在java线程池的实现原理源码分析问题上存在疑惑,小编查阅了各式资 ... [详细]
  • React 小白初入门
    推荐学习:React官方文档:https:react.docschina.orgReact菜鸟教程:https:www.runoob.c ... [详细]
  • #ReactivityFundamentals#DeclaringReactiveState ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
author-avatar
绿茶2602921445
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有