shfshanyue / Daily-Question

互联网大厂内推及大厂面经整理,并且每天一道面试题推送。每天五分钟,半年大厂中

Home Page:https://q.shanyue.tech

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

【Q474】在 react 中,以下父子组件的 useEffect/useLayoutEffect 顺序如何

shfshanyue opened this issue · comments

以下代码在控制台里如何按序输出,代码见 codesandbox

import { useEffect, useLayoutEffect } from "react";
import "./App.css";

function Child() {
  console.log("Child: Render");

  useEffect(() => {
    console.log("Child: useEffect");
  });

  useLayoutEffect(() => {
    console.log("Child: useLayoutEffect");
  });

  return <div className="App">Child</div>;
}

function App() {
  console.log("App: render");

  useEffect(() => {
    console.log("App: useEffect");
  });

  useLayoutEffect(() => {
    console.log("App: useLayoutEffect");
  });

  return (
    <div className="App">
      App
      <Child />
    </div>
  );
}

export default App;

不太会,跑了下,运行结果如下
https://stackblitz.com/edit/vitejs-vite-ibcjhf?file=src%2FApp.jsx

App: render
Child: Render
Child: useLayoutEffect
App: useLayoutEffect
Child: useEffect
App: useEffect

学习了下面两篇文章:
https://jser.dev/2023-07-08-how-does-useeffect-work
https://jser.dev/react/2021/12/04/how-does-useLayoutEffect-work

总结一下我的理解:
1、useEffect 通过 scheduleCallback调度的,是异步执行的,也就是在渲染到页面后执行
而useLayoutEffect 是同步执行的,发生在dom mutation更新了dom结构,但是还未绘制到屏幕之前
2、useEffect 和 useLayoutEffect 都是递归执行的,先执行子组件
3、有useEffect 和 useLayoutEffect的fiber会被打上标记,加入到effectList中, 每次更新都会都会处理, 两个函数都会处理成effectObject, 包含create、destory属性,其中create是useEffect 和 useLayoutEffect传入的函数,destory对应传入的函数执行返回的函数,在commit阶段,每次都是先执行destory清理函数,然后执行create, 挂载时destory为undefined,跳过清理函数执行,执行create,执行后把return的函数复制给destory, 下一次更新时destory不为undefined就会执行destory销毁函数,如果dep有变化接下来执行create