Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Коли React виконує useLayoutEffect()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`useLayoutEffect()`** React виконує одразу після оновлення реального DOM, але ще до того, як браузер "намалює" зміни користувачу (до paint). **Ключове:** саме тому `useLayoutEffect` придатний для синхронних DOM-вимірювань і позиціонування, які запобігають візуальному "стрибку" інтерфейсу, а `useEffect`, що виконується після paint, підходить для асинхронних побічних дій на кшталт запитів до API.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Коли React виконує `useLayoutEffect()` React викликає `useLayoutEffect()` **після того, як**: 1. компонент **відрендерений у віртуальному DOM**, 2. **реальний 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` |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.