写点什么

面试官:useLayoutEffect 和 useEffect 的区别

作者:全栈潇晨
  • 2021 年 12 月 15 日
  • 本文字数:1194 字

    阅读完需:约 4 分钟

面试官:useLayoutEffect 和 useEffect 的区别

hello,这里是潇晨,大家面试的过程中有没有遇到过这样的问题呢,useLayoutEffect 和 useEffect 的区别是什么,大家可能会回答 useEffect 是异步的,useLayoutEffect 是同步的,这样回答面试官真的会满意慢,我们需要说清楚他们在源码中的调用时机。


先来看个例子:点击触发更新之后,如果 count 之前的状态是 0,我们随机生成一个数字,在阻塞一段时间,在设置 count 位随机值,看看在 useEffect 和 useLayoutEffect 这两种情况下会有什么不同


import React, { useLayoutEffect, useState, useEffect } from "react";
export default function App() { const [count, setCount] = useState(0); //用 useLayoutEffect 试试 useEffect(() => { if (count === 0) { const randomNum = Math.random() * 100;//随机生成一个数字
const now = performance.now();
while (performance.now() - now < 100) {//阻塞一段时间 console.log('blocking...'); }
setCount(randomNum);//重新设置状态,设置成随机数 } }, [count]);
return <div onClick={() => setCount(0)}>{count}</div>;}
//在useEffect的情况下,不断点击触发更新,偶尔会显示0//在useLayoutEffect的情况下,不断点击触发更新,不会偶现0
复制代码


在源码中不管首次渲染还是更新的时候都会经历一个阶段叫 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 同步调用



详细源码调试视频(高效学习):点击学习

往期 react 源码解析文章:

1.开篇介绍和面试题


2.react的设计理念


3.react源码架构


4.源码目录结构和调试


5.jsx&核心api


6.legacy和concurrent模式入口函数


7.Fiber架构


8.render阶段


9.diff算法


10.commit阶段


11.生命周期


12.状态更新流程


13.hooks源码


14.手写hooks


15.scheduler&Lane


16.concurrent模式


17.context


18事件系统


19.手写迷你版react


20.总结&第一章的面试题解答

用户头像

全栈潇晨

关注

还未添加个人签名 2021.02.17 加入

还未添加个人简介

评论

发布
暂无评论
面试官:useLayoutEffect和useEffect的区别