Skip to main content

Що робить useLayoutEffect() при SSR?

Нагадаємо: що робить useLayoutEffect() у клієнтському React

useLayoutEffect() - це "синхронний" аналог useEffect():

ХукКоли спрацьовує
useEffect()вже після того, як браузер намалював DOM (асинхронно)
useLayoutEffect()одразу після того, як React оновив DOM, але до відмальовки екрана

Тобто useLayoutEffect() дозволяє:

  • виміряти розміри елементів,
  • синхронно змінити layout,
  • або виконати DOM-мутації до того, як користувач побачить екран.

Що відбувається при SSR

При Server-Side Rendering React не має доступу до DOM.

  • Немає window,
  • немає document,
  • немає реальних елементів.

А отже, будь-які DOM-операції всередині useLayoutEffect() неможливі.

Тому React взагалі не викликає цей хук на сервері.


Поведінка useLayoutEffect() в SSR

На сервері:

  • React повністю ігнорує всі useLayoutEffect() (і useEffect() теж).
  • Тобто код всередині не виконається взагалі.
  • Компонент рендериться "чисто" - лише повертає JSX -> HTML.

На клієнті (після гідрації):

  • React виконає useLayoutEffect() один раз, коли гідрація завершиться і DOM уже доступний.
  • Якщо в хук закладені побічні ефекти, вони спрацюють лише після того, як HTML вже з'явився в браузері.

Можлива проблема - попередження в консолі

Якщо ти використовуєш useLayoutEffect() всередині компонента, що рендериться і на сервері, і на клієнті, React може вивести попередження:

javascript
Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer's output format.

або

javascript
Warning: useLayoutEffect is not supported during server rendering.

Це не помилка, а попередження: React просто повідомляє, що твій layout-ефект буде проігнорований під час SSR.


Як уникнути проблем

Варіант 1. Замінити useLayoutEffect на useEffect, якщо можна

Якщо твій код не залежить від точного вимірювання DOM, краще просто використати useEffect:

javascript
useEffect(() => { console.log('Безпечно для SSR'); }, []);

Варіант 2. Обгортати виклик у перевірку середовища

Якщо тобі все-таки потрібен useLayoutEffect (наприклад, для canvas, вимірювань і анімацій), можна безпечно визначити "універсальний" хук:

javascript
import { useLayoutEffect, useEffect } from 'react'; // Безпечний хук для SSR export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;

Тепер можна писати:

javascript
useIsomorphicLayoutEffect(() => { const rect = ref.current.getBoundingClientRect(); console.log(rect); }, []);

На сервері виконається useEffect (тобто нічого не станеться), а в браузері - справжній useLayoutEffect.


Варіант 3. Виконувати DOM-залежний код лише після гідрації

javascript
const [hydrated, setHydrated] = useState(false); useEffect(() => { setHydrated(true); }, []); if (!hydrated) return null; useLayoutEffect(() => { // Цей код виконається лише на клієнті, після гідрації }, []);

Резюме

СередовищеЩо робить useLayoutEffect()
Сервер (SSR)Повністю ігнорується - не викликається, DOM недоступний
Клієнт (після гідрації)Виконується синхронно після вставки HTML у DOM
Якщо використовується в SSR-компонентіМоже викликати попередження, але не помилку
РішенняВикористати useIsomorphicLayoutEffect або useEffect

Ключова думка

useLayoutEffect не працює на сервері. React просто пропускає його під час SSR, а виконує лише після того, як HTML уже відрендерений і "оживлений" на клієнті.

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

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

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