In react 18.0, why asynchronous useLayoutEffect's callback and asynchronous useEffect's callback cannot cause UI flickering during 'First Paint'?

439 views Asked by At

I am new in React.js and cannot completely understand the source code.

As I can see in the source code of react 18.0, my function defined in useLayoutEffect or useEffect is called by MessageChannel API's postMessage asynchronously during 'First Paint'.

useLayoutEffect breakpoint screenshot

useEffect breakpoint screenshot

But, why DOM changes writen in my function (either in useLayoutEffect or useEffect) cannot cause UI flickering during 'First Paint' according to the performance tab in Chrome browser's dev tools.

frame timing screenshot

Header/index.jsx

import React, { useEffect, useLayoutEffect } from "react";
import logoUrl from "./logo.png";
import style from "../../../index.css";
import { useState } from "react";

import { randomFruit, pick } from "./pickRandomFruitCreator";

export default function Header() {
  const [fruit, setFruit] = useState(randomFruit);
  const text = `change fruit to: ${fruit}`;
  const obj = {
    some: {
      text,
    },
  };

  useEffect(() => {
    const ele = document.getElementsByTagName('button')[0];
    ele.textContent =  'useEffect'
    console.log("useEffect finished");
  }, [obj]);

  useLayoutEffect(() => {
    // const ele = document.getElementsByTagName("button")[0];
    // ele.textContent = "uselayoutEffect";
    console.log("useLayoutEffect finished");
  }, [obj]);

  const onchange = () => {
    pick();
    setFruit(randomFruit);
  };

  return (
    <>
      <header>
        <h1>Header</h1>
      </header>
      <img src={logoUrl} />
      <button className={style.changeState} onClick={onchange}>
        {text}
      </button>
    </>
  );
}

Header/pickRandomFruitCreator.js

const fruits = ['banana', 'apple', 'orange'];
let pickerIndex = 0;
let randomFruit = fruits[pickerIndex];

const pick = () => {
  pickerIndex = pickerIndex + 1;
  if (pickerIndex > fruits.length - 1) {
    pickerIndex = 0;
  }
  randomFruit = fruits[pickerIndex]
}


export { pick, randomFruit }
0

There are 0 answers