skip to Main Content

I have an question about when will the useLayoutEffect callback be triggered and when will the screen be drawn.

Consider the following code:

export default function CompA() {
  const [count, setCount] = useState(0);

  useLayoutEffect(() => {
    // I'll debug here after initial render 
    console.log('CompA layoutEffectCallback');
  });

  useEffect(() => {
    console.log('CompA updateEffectCallback');
  }, [count]);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div onClick={handleClick}>
      CompA
      <h1>{count}</h1>
    </div>
  );
}

After the initial render, the screen displays the number 0,then I set a chrome devtool debugger in the callback of the useLayoutEffect hook before I click the div. After click, the function execution is paused at debugger, but I see the screen already shown number 1.

The docs said that useLayoutEffect fires before the browser repaints the screen,but I don’t understand why the screen has updated.

screenshot

2

Answers


  1. The useLayoutEffect hook runs synchronously after the DOM is updated but before the browser repaints.

    Initially, you rendered CompA, and the initial state of count was 0. Then, you clicked the div and count was increased to 1.

    Since useLayoutEffect is ran after the DOM has been updated BUT before it repaints, the layout effect will log CompA layoutEffectCallback right before the browser performs the paint. This is why you see the screen showing "1" even when the debugger is paused in useLayoutEffect. The DOM has already been updated with the new state before the browser is notified to render it.

    Login or Signup to reply.
  2. Pausing/break-pointing in the useLayoutEffect callback doesn’t prevent/block the browser from repainting. It’s merely a place you can "hook" into and apply some logic like measuring the computed DOM before the browser repaints. You will still see the updated DOM and repainted view regardless.

    Here’s a handy, albeit a bit outdated, diagram of the React component lifecycle:

    enter image description here

    useLayoutEffect is called in roughly the "pre-commit phase" where it can check the computed DOM. useEffect would be called later/after the "commit phase".

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search