Skip to main content

Коли React виконує useLayoutEffect()?

Коли React виконує useLayoutEffect()

React викликає useLayoutEffect() після того, як:

  1. компонент відрендерений у віртуальному DOM,
  2. реальний DOM уже оновлений (елементи вставлені/змінені), але ще до того, як браузер "показав" зміни користувачу (перед paint).

Тобто:

useLayoutEffect виконується одразу після React DOM mutations, але до "фарбування" (paint) екрана.


Покроковий цикл оновлення React

Ось як React обробляє один рендер-процес:

ЕтапЩо відбуваєтьсяКоли викликається
1. Render phaseReact викликає функції компонентів -> створює віртуальне дерево елементівдо DOM-змін
2. Commit phase (DOM updates)React оновлює реальний DOM (вставка, видалення, зміни)тут DOM уже готовий
3. useLayoutEffectВикликається одразу після оновлення DOM, але до відображення користувачусаме тут
4. Browser PaintБраузер візуально малює зміни на екраніпісля layout-ефектів
5. useEffectВиконується після того, як зміни вже показанідля асинхронних ефектів

Візуальна шкала:

javascript
RenderDOM оновлено → [useLayoutEffect()]Paint (екран)[useEffect()]

Приклад для розуміння

javascript
import { useLayoutEffect, useEffect } from "react"; function Example() { useLayoutEffect(() => { console.log("useLayoutEffect"); }); useEffect(() => { console.log("useEffect"); }); console.log("Render"); return <div>Приклад</div>; }

Лог у консолі:

javascript
Render useLayoutEffect useEffect

Тобто спочатку React рендерить компонент, потім викликає layout-ефект, і вже після показу сторінки - звичайний ефект.


Навіщо потрібний такий порядок

useLayoutEffect:

  • Використовується для синхронних ефектів, які впливають на DOM (наприклад, вимірювання, позиціонування, скрол).
  • Виконується до paint, щоб користувач не побачив "стрибок" інтерфейсу.

useEffect:

  • Використовується для асинхронних і побічних дій, які не впливають на DOM (наприклад, запити до API, логування).
  • Виконується після paint, щоб не блокувати відмальовку UI.

Приклад, де порядок важливий

З useEffect (користувач бачить "мигання"):

javascript
function Box() { const ref = useRef(); useEffect(() => { ref.current.style.transform = "translateY(50px)"; }, []); return <div ref={ref} style={{ width: 100, height: 100, background: "tomato" }} />; }

Проблема: React спочатку рендерить div -> браузер показує його -> потім спрацьовує useEffect -> "стрибок".


З useLayoutEffect (жодного мигання):

javascript
useLayoutEffect(() => { ref.current.style.transform = "translateY(50px)"; }, []);

Тепер стиль застосується до відмальовки, і користувач одразу побачить коректне положення блоку.


Важливо пам'ятати

ПравилоПояснення
useLayoutEffect виконується синхронноReact чекає його завершення перед "paint"
Може блокувати відмальовкуНе зловживай, особливо для важких обчислень
Використовуй лише для DOM-вимірювань і синхронізаціїВсе інше - через useEffect
На сервері (SSR) викликати не можнаReact замінює useLayoutEffect на useEffect на сервері (щоб уникнути помилок)

Підсумок

ПитанняВідповідь
Коли React виконує useLayoutEffect()Після оновлення DOM, але до того, як браузер "пофарбує" екран
У якому порядкуrender → commit → useLayoutEffect → paint → useEffect
Для чого потрібнийДля вимірювання DOM, синхронізації позицій, запобігання "миганням"
Коли не використовуватиДля запитів, логів, асинхронних ефектів - для цього useEffect

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.