面试官:useLayoutEffect 和 useEffect 的区别
面试官:useLayoutEffect 和 useEffect 的区别
hello,这里是潇晨,大家面试的过程中有没有遇到过这样的问题呢,useLayoutEffect 和 useEffect 的区别是什么,大家可能会回答 useEffect 是异步的,useLayoutEffect 是同步的,这样回答面试官真的会满意慢,我们需要说清楚他们在源码中的调用时机。
先来看个例子:点击触发更新之后,如果 count 之前的状态是 0,我们随机生成一个数字,在阻塞一段时间,在设置 count 位随机值,看看在 useEffect 和 useLayoutEffect 这两种情况下会有什么不同
在源码中不管首次渲染还是更新的时候都会经历一个阶段叫 commit 阶段,这个阶段主要的工作就是处理一些钩子函数、生命周期、遍历 render 阶段形成的 EffectList 链表,将带有副作用的 Fiber 节点应用到真实节点上,如果对 render 阶段不了解可以参阅往期文章 render阶段 ,下面这张图是 commit 阶段源码的结构图,我们详细的讲解一下。
在 commitRootImpl 的函数中主要分三个部分:
commit 阶段前置工作
mutation 阶段
调用 commitBeforeMutationEffects,scheduleCallback 调度执行 flushPassiveEffects
调用 commitMutationEffects,处理相关的副作用,操作真实节点 useLayoutEffect 的销毁函数在这个函数中执行
调用 commitLayoutEffects,调用 commitLayoutEffects 的回调函数,这个时候副作用已经应用到真实节点了,所以能拿到最新的节点。
在 commit 阶段结束之后 flushPassiveEffects 执行 useEffect 的销毁函数和回调函数。
commit 阶段收尾工作
所以 useLayout/componentDidMount 和 useEffect 的区别是什么?
答:他们在 commit 阶段不同时机执行,useEffect 在 commit 阶段结尾异步调用,useLayout/componentDidMount 同步调用
评论