iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >useEffect返回函数执行过程是什么
  • 839
分享到

useEffect返回函数执行过程是什么

2023-07-06 05:07:26 839人浏览 独家记忆
摘要

本文小编为大家详细介绍“useEffect返回函数执行过程是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“useEffect返回函数执行过程是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。下面是源码简化

本文小编为大家详细介绍“useEffect返回函数执行过程是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“useEffect返回函数执行过程是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

下面是源码简化:

function recursivelyTraversePassiveUnmountEffects(parentFiber: Fiber): void {  const deletions = parentFiber.deletions;  if ((parentFiber.flags & ChildDeletion) !== NoFlags) {    if (deletions !== null) {      for (let i = 0; i < deletions.length; i++) {        const childToDelete = deletions[i];        nextEffect = childToDelete;        commitPassiveUnmountEffectsInsideOfDeletedTree_begin(          childToDelete,          parentFiber        );      }    }  }}function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(  deletedSubtreeRoot: Fiber,  nearestMountedAncestor: Fiber | null) {  while (nextEffect !== null) {    const fiber = nextEffect;    // 执行 passive effects 返回的函数    commitPassiveUnmountInsideDeletedTreeOnFiber(fiber, nearestMountedAncestor);    const child = fiber.child;    if (child !== null) {      child.return = fiber;      nextEffect = child;    } else {      commitPassiveUnmountEffectsInsideOfDeletedTree_complete(        deletedSubtreeRoot      );    }  }}function commitPassiveUnmountEffectsInsideOfDeletedTree_complete(  deletedSubtreeRoot) {  while (nextEffect !== null) {    const fiber = nextEffect;    const sibling = fiber.sibling;    const returnFiber = fiber.return;    if (fiber === deletedSubtreeRoot) {      nextEffect = null;      return;    }    if (sibling !== null) {      sibling.return = returnFiber;      nextEffect = sibling;      return;    }    nextEffect = returnFiber;  }}

deletions

在正式开始之前,我们要了解一个 fiber 的属性:deletions

这个属性存放的是当前节点中被删除的 fiber,这个数组是在 commit 阶段被赋值的

如果有被删除的节点,这个属性值是一个数组,如果没有被删除的节点,这个属性值是 null

const A = () => {  useEffect(() => {    return () => {      console.log("A unmount");    };  }, []);  return <div>文本A</div>;};const B = () => {  useEffect(() => {    return () => {      console.log("B unmount");    };  }, []);  return <div>文本B</div>;};

如果 App 组件这样写,那么 deletions 的值是 [Fibernode, FiberNode]

const App(){  const [count, setCount] = useState(0)  return <div>    {count % 2 === 0 && <A />}    {count % 2 === 0 && <B />}    <div onClick={()=> setCount(count+1)}>+1</div>  </div>}

如果 App 组件这样写,那么 deletions 的值是 [FiberNode]

const App(){  const [count, setCount] = useState(0)  return <div>    {count % 2 === 0 && <><A /><B /></>}    <div onClick={()=> setCount(count+1)}>+1</div>  </div>}

对于第二种情况,React 会把 A 组件和 B 组件作为一个整体,所以 deletions 的值是 [FiberNode]

处理当前节点的 deletions

react 在遍历 fiber tree 时,会先处理当前的 fiberdeletions,等处理完之后再遍历下一个 fiber

现在我们已经知道 deletions 中保存的是当前 fiber 下被删除的子节点

这时 react 会遍历 deletions 数组,然后执行每个 fiberpassive effect 返回的函数

但是有个问题,如果 deletions 中的 fiber 有子节点,那么这些子节点也会被删除,这时 react 会怎么处理呢?

这里分两种情况来讨论:

  • 删除的 fiber 没有子节点:<div>{xxxx && <A />}</div>

  • 删除的 fiber 有子节点:<div>{xxxx && <><A /><B /></>}</div> -->

删除的 fiber 没有子节点:<div>{xxxx && <A />}</div>

这种情况比较好理解

当遍历到 div 时,因为 <A/> 节点会被卸载,所以在 divdeletions 保存了一个 <A/>fiber

遍历 deletions 数组,执行 <A/>passive effect 返回的函数

如下图所示:

useEffect返回函数执行过程是什么

删除的 fiber 有子节点:<div>{xxxx && <><A /><B /></>}</div>

这种情况就比较复杂了

当遍历到 div 时,<></> 节点会被卸载,所以在 divdeletions 保存了一个 <></>fiber

遍历 deletions 数组,执行 fiberpassive effect 返回的函数,对于 <></> 来说是不存在的 passive effect

那么这个时候就要去遍历它的 child.fiber,也就是 <A/><B/>

首先拿到第一个 fiber,也就是 <A/>,然后执行 <A/>passive effect 返回的函数,这步比较好理解

child = fiber.child;if (child !== null) {  nextEffect = child;}

这里遍历也是深度优先,遍历一个 child,执行一个 passive effect 返回函数,然后再遍历下一个 child(这边 <A /> 已经是叶子节点了)

然后拿到第二个 fiber,也就是 <B/>,然后执行 <B/>passive effect 返回的函数,这步就不太好理解了

child = fiber.child;if (child !== null) {  nextEffect = child;} else {  commitPassiveUnmountEffectsInsideOfDeletedTree_complete(deletedSubtreeRoot);}

这里要注意的是:

react 在寻找有 passive effectfiber 时,只遍历到有 passive effectfiber, 像 div 这种没有 passive effect 就不会遍历

但是在处理 deletionsreact 会遍历所有的 fiber,也就是说从当前的 fiber 开始,一直往下遍历到叶子节点,这个叶子节点是指文本节点这种,往下不会有节点了(对于 A 组件来说 文本A 是文本节点)

然后在开始往上遍历,往上遍历是调用 commitPassiveUnmountEffectsInsideOfDeletedTree_complete 函数,直到遍历到 deletionRoot,在向上遍历的过程中会检查是否有 sibling,如果有说明 sibling 还没被处理,这样就找到了 <B/>,然后执行 <B/>passive effect 返回的函数

如下图所示:

useEffect返回函数执行过程是什么

向下遍历和向上遍历

在处理 deletions 时,对于每个 deletedNode,都先向下遍历,然后再向上遍历

  • 向下遍历:commitPassiveUnmountEffectsInsideOfDeletedTree_begin(深度优先,优先处理左边的节点)

  • 向上遍历:commitPassiveUnmountEffectsInsideOfDeletedTree_complete(之后再处理右边节点)

总结

1. 遍历 deletions 数组:

  • react 在处理 deletions 时,先沿着 fiber tree 向下遍历,如果有 passive effect 返回的函数,则执行

  • 一直遍历到没有 childfiber,再向上遍历,处理 sibling

  • 再向上遍历时,如果如果遇到 sibling,再向下遍历,向下遍历时遇到 passive effect 返回的函数,则执行

  • 如此循环直到遍历到 deletedNode,结束遍历

2. 结合掌握 React 组件树遍历技巧

  • 遍历寻找有 passive effect 节点

    • react 从根组件向下遍历,如果没有 passive effect,则不会遍历

  • 遍历时,如果遇到当前节点有 deletions 时,会暂停寻找 passive effect 节点

    • 进入遍历 deletions 数组

react 遍历 deletions 完整逻辑如下图所示:

图中绿色部分是遍历 deletionsNode 过程,红色部分是遍历寻找 passive effect 过程

useEffect返回函数执行过程是什么

读到这里,这篇“useEffect返回函数执行过程是什么”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: useEffect返回函数执行过程是什么

本文链接: https://www.lsjlt.com/news/357843.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • useEffect返回函数执行过程是什么
    本文小编为大家详细介绍“useEffect返回函数执行过程是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“useEffect返回函数执行过程是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。下面是源码简化...
    99+
    2023-07-06
  • useEffect 返回函数执行过程源码解析
    目录引言deletions处理当前节点的 deletions删除的 fiber 没有子节点:删除的 fiber 有子节点:向下遍历和向上遍历总结1. 遍历 deletions 数组:...
    99+
    2023-05-16
    useEffect 返回函数执行流程 useEffect 返回函数
  • JavaScript函数的执行过程是什么
    JavaScript函数的执行过程是什么?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。JavaScript可以做什么1.可以使网页具有交互性,例如响应用户点击,...
    99+
    2023-06-14
  • js中递归函数的执行过程是什么
    在JavaScript中,递归函数的执行过程如下:1. 当调用递归函数时,程序会首先执行函数体内的代码。2. 在函数体内,如果遇到递...
    99+
    2023-09-15
    js
  • ShellExecute函数返回值是什么
    ShellExecute函数的返回值是一个HINSTANCE类型的值,它表示执行操作的实例句柄。如果函数执行成功,返回值为大于32的...
    99+
    2023-08-08
    ShellExecute
  • php执行过程是什么
    PHP执行过程包括以下几个步骤:1. 服务器接收到客户端发送的PHP文件请求。2. 服务器将请求的PHP文件发送给PHP解析器进行解...
    99+
    2023-09-05
    php
  • java先返回再执行的方法是什么
    Java中的方法可以分为两种执行方式:同步执行和异步执行。同步执行是指方法按照顺序逐个执行,直到方法执行完毕后再返回到调用者。这是J...
    99+
    2023-09-17
    java
  • python中函数返回值是什么
    python中函数的返回值包含指定返回值和隐含返回值两种指定返回值当函数中有return语句时,return语句的结果就是函数的返回值。例:def info(x):return x +1函数返回值为x+1,其中x为函数的参数。隐含返回值如函...
    99+
    2024-04-02
  • Golang函数的执行流程是什么?
    go 函数的执行流程如下:分配栈空间,存储局部变量和参数。压栈调用者信息,准备返回。设置局部变量。执行函数体(语句和表达式)。返回值(如果有)。恢复调用者信息。释放栈空间。控制权返回给调...
    99+
    2024-04-11
    golang 函数执行流程
  • golang函数的返回值是什么?
    go 语言函数返回值是类型化的:函数返回值必须具有指定类型。函数可以返回多个值,使用逗号分隔,并可使用命名返回值提高可读性。未指定返回值类型的函数将返回空值(nil)。 Go 语言函数...
    99+
    2024-04-22
    返回值 golang
  • Golang 函数值返回的是什么?
    golang 函数可以返回多个值,在函数签名中指定返回值类型。例如,函数 sumandcheck(a, b int) 返回整数和布尔值。若要弃用未使用值,请使用下划线 _ 作为变量,例如...
    99+
    2024-04-14
    golang 函数值
  • struts2的执行过程是什么
    Struts2的执行过程可以分为以下几个步骤:1. 客户端发送请求:客户端通过浏览器向服务器发送HTTP请求。2. 请求被Strut...
    99+
    2023-08-18
    struts2
  • PHP 函数返回回调函数的常见场景是什么?
    php 函数可以返回回调函数,用于处理事件、排序数组、延迟执行代码和过滤集合。 PHP 函数返回回调函数的常见场景 在 PHP 中,函数可以返回回调函数,这意味着它返回一个可以像函数一...
    99+
    2024-04-19
    php 函数式编程 laravel
  • jdbc执行存储过程是什么
    JDBC(Java Database Connectivity)执行存储过程是通过Java程序连接到数据库,并调用数据库中定义的存储...
    99+
    2023-10-24
    jdbc
  • php代码执行过程是什么
    PHP代码执行过程包括以下步骤:1. 服务器接收到客户端的HTTP请求,查找对应的PHP文件。2. 服务器调用PHP解释器(如PHP...
    99+
    2023-08-29
    php
  • Python函数的返回值与嵌套函数是什么
    这篇文章主要介绍“Python函数的返回值与嵌套函数是什么”,在日常操作中,相信很多人在Python函数的返回值与嵌套函数是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python函数的返回值与嵌套函数...
    99+
    2023-06-02
  • python中返回函数的作用是什么
    这期内容当中小编将会给大家带来有关python中返回函数的作用是什么,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。python可以做什么Python是一种编程语言,内置了许多有效的工具,Python几乎无...
    99+
    2023-06-14
  • oracle窗口函数的执行流程是什么
    Oracle窗口函数的执行流程大致如下: 首先,确定窗口函数所应用的数据集,即确定数据集的排序顺序和分区方式。 接着,对数据...
    99+
    2024-04-09
    oracle
  • PHP 函数返回 NULL 的意义是什么?
    php 函数返回 null 表示函数没有返回值、遇到错误、或特意返回 null。例如,finduser 函数根据数据库查询结果返回用户对象或 null,若用户不存在则返回 null。 ...
    99+
    2024-04-21
    php 返回null
  • golang函数返回值的类型是什么?
    go 函数可返回一个或多个类型的值,需在签名中明确指定。单返回值函数返回特定类型的单个值,而多返回值函数返回按顺序指定类型的多个值。实际应用中,如计算两个数字最大公约数 (gcd) 的函...
    99+
    2024-04-22
    返回值 golang 类型 最大公约数
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作