Коли варто використовувати useLayoutEffect?
Коротко: навіщо він потрібен
useLayoutEffect() - це версія useEffect(),
яка виконується одразу після того, як React оновив DOM,
але до того, як браузер намалював (paint) зміни на екрані.
Тобто він дає можливість:
виміряти або змінити DOM до того, як користувач його побачить.
Використовуй useLayoutEffect, коли потрібно:
1. Виміряти DOM до відмальовки
Якщо ти хочеш отримати точні розміри або позицію елемента
(наприклад, для обчислення положення спливаючого вікна, тултипа, каретки тощо),
використовуй useLayoutEffect, щоб браузер не встиг відмалювати "старий" стан.
function Tooltip({ text }) {
const ref = useRef(null);
useLayoutEffect(() => {
const { width, height } = ref.current.getBoundingClientRect();
console.log("Розміри елемента до відображення:", width, height);
}, []);
return <div ref={ref}>{text}</div>;
}Чому не useEffect:
у useEffect вимірювання відбудуться після відмальовки,
і дані можуть бути вже неактуальними (або спричинять "стрибок").
2. Синхронізувати візуальний стан з DOM
Якщо ти вручну змінюєш DOM (наприклад, позиціонуєш, скролиш або застосовуєш анімацію),
і не хочеш, щоб користувач бачив проміжний стан,
роби це у useLayoutEffect.
useLayoutEffect(() => {
elementRef.current.scrollTop = elementRef.current.scrollHeight;
}, [messages]);Таким чином скрол відбудеться до того, як контент відобразиться, і не буде візуального "стрибка".
3. Запобігти "миготінню" або "стрибку" інтерфейсу
Іноді при завантаженні компонента ти змінюєш розміри, позиції, класи тощо.
Якщо зробити це через useEffect, React покаже старий UI,
а потім "перебудує" - користувач побачить "спалах".
Використання useLayoutEffect вирішує це:
useLayoutEffect(() => {
ref.current.style.transform = "translateY(50px)";
}, []);Ефект застосовується до paint, і користувач одразу бачить фінальний вигляд.
4. Синхронізація анімацій
Якщо ти працюєш з бібліотеками анімацій (Framer Motion, GSAP, Anime.js тощо) і потрібно, щоб анімація стартувала у точний момент перед відмальовкою,
useLayoutEffectдає цю точність.
useLayoutEffect(() => {
gsap.from(ref.current, { opacity: 0, y: -20, duration: 0.3 });
}, []);5. Коли логіка залежить від негайного оновлення DOM
Іноді ти змінюєш стан, і одразу після цього маєш прочитати актуальні розміри/позиції.
useEffect буде занадто пізно, тому що браузер вже "показав" старий стан.
Приклад - обчислення висоти блока при зміні стану:
useLayoutEffect(() => {
const h = ref.current.offsetHeight;
console.log("Актуальна висота:", h);
}, [isOpen]);Коли НЕ варто використовувати useLayoutEffect
| Випадок | Чому погано |
|---|---|
| Для API-запитів, таймерів, логів | Блокує відмальовку без причини |
| Для логіки, не пов'язаної з DOM | Не має сенсу |
| Часто оновлюваний ефект | Уповільнить FPS - React чекатиме завершення кожного layout-ефекту |
| При SSR (Next.js та ін.) | React видасть попередження: "useLayoutEffect does nothing on the server" |
Ідеальне правило:
Використовуй
useLayoutEffectлише для DOM-операцій, які потрібно виконати до того, як користувач побачить екран. Все інше - уuseEffect.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.