Коли React виконує useLayoutEffect()?
Коли React виконує useLayoutEffect()
React викликає useLayoutEffect() після того, як:
- компонент відрендерений у віртуальному DOM,
- реальний DOM уже оновлений (елементи вставлені/змінені), але ще до того, як браузер "показав" зміни користувачу (перед paint).
Тобто:
useLayoutEffectвиконується одразу після React DOM mutations, але до "фарбування" (paint) екрана.
Покроковий цикл оновлення React
Ось як React обробляє один рендер-процес:
| Етап | Що відбувається | Коли викликається |
|---|---|---|
| 1. Render phase | React викликає функції компонентів -> створює віртуальне дерево елементів | до DOM-змін |
| 2. Commit phase (DOM updates) | React оновлює реальний DOM (вставка, видалення, зміни) | тут DOM уже готовий |
3. useLayoutEffect | Викликається одразу після оновлення DOM, але до відображення користувачу | саме тут |
| 4. Browser Paint | Браузер візуально малює зміни на екрані | після layout-ефектів |
5. useEffect | Виконується після того, як зміни вже показані | для асинхронних ефектів |
Візуальна шкала:
javascript
Render → DOM оновлено → [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
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.