Sobes.tech
Middle+

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

sobes.tech MI

Válasz az MI-től

React-ben a hook-ok hívási és végrehajtási sorrendje a következő:

  • Minden rendereléskor először a komponens törzse fut le, ahol a console.log("each render 2") hívódik.
  • Ezután a useLayoutEffect kerül meghívásra, amely szinkron módon fut le közvetlenül a DOM módosítása után, de még azelőtt, hogy a böngésző megrajzolná a változásokat. Itt a console.log("each render 1") kerül meghívásra.
  • Miután a böngésző megrajzolta a változásokat, a useEffect kerül meghívásra, ahol a console.log("each render 3") fut le.

Így a komponens mountolásakor és frissítésekor a logok sorrendje:

each render 2
each render 1
each render 3

A komponens leválasztásakor a useEffect és useLayoutEffect visszatérhetnek tisztító függvényekkel, de ebben a példában nincsenek, így leválasztáskor nem lesz log.

Példa magyarázattal:

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>
  );
}

Fontos: A useLayoutEffect blokkolja a renderelést a végrehajtásáig, míg a useEffect aszinkron módon fut a renderelés után.