Sobes.tech
Middle+

import React, { useState, useEffect, useLayoutEffect } from 'react'; export default () => { const [count, setCount] = useState(0); useLayoutEffect(() => console.log("each render 1")); console.log("each render 2"); useEffect(() => console.log("each render 3")); return ( <button onClick={() => setCount((prevProps) => ++prevProps)}> Increment </button> ); } // mount -> each render 2, each render 1, each render 3 // update -> each render 2, each render 1, each render 3 // unmount 4

sobes.tech AI

Answer from AI

In React, the order of hook calls and logs is as follows:

  • During each render, the component body executes first, where console.log("each render 2") is called.
  • Then, useLayoutEffect is called, which runs synchronously immediately after DOM changes but before the browser repaints. Inside it, console.log("each render 1") is called.
  • After the browser has painted the changes, useEffect is called, where console.log("each render 3") is executed.

Thus, during mounting and updating, the log order will be:

each render 2
each render 1
each render 3

During unmounting, useEffect and useLayoutEffect can return cleanup functions, but in this example, they do not, so there are no logs during unmounting.

Example with explanations:

import React, { useState, useEffect, useLayoutEffect } from 'react';

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

  useLayoutEffect(() => {
    console.log("each render 1");
  });

  console.log("each render 2");

  useEffect(() => {
    console.log("each render 3");
  });

  return (
    <button onClick={() => setCount(prev => prev + 1)}>
      Increment
    </button>
  );
}

Important: useLayoutEffect blocks painting until it runs, whereas useEffect runs asynchronously after painting.

import React, { useState, useEffect, useLayoutEffect… - sobes.tech