Перейти к содержанию
Innovialabs

Что такое гидратация и как исправить ошибки гидратации

Продвинутое3 мин

Коротко

Гидратация — это момент, когда React в браузере «оживляет» готовый серверный HTML, подключая к нему обработчики событий. Ошибка гидратации возникает, если первый рендер в браузере отличается от серверного, и лечится тем, что всё нестабильное (даты, случайные значения, window) переносится в эффект или клиентский компонент.

Что такое гидратация

При серверном рендеринге (SSR или SSG) браузер сразу получает готовый HTML: текст и картинки видны, но кнопки ещё не работают. Затем загружается JavaScript, и React проходит по этому HTML, строит у себя то же дерево компонентов и подключает обработчики событий к уже существующим элементам. Этот процесс и называется гидратацией.

Ключевое условие: React ожидает, что первый рендер на клиенте даст точно такой же результат, как на сервере. Если результат отличается, возникает ошибка гидратации (hydration mismatch).

Сколько стоит гидратация

Гидратация не бесплатна:

  • браузеру нужно скачать, разобрать и выполнить JavaScript всех интерактивных компонентов;
  • пока она не завершилась, страница выглядит готовой, но может не реагировать на клики;
  • на слабых телефонах это заметно ухудшает отзывчивость.

Как снизить стоимость:

  • Server Components (в React и Next.js App Router) не гидратируются вовсе — их JavaScript не попадает в браузер. Делайте клиентскими только интерактивные части.
  • Не ставьте "use client" наверх дерева — всё, что ниже, станет клиентским.
  • Ленивая загрузка тяжёлых виджетов (dynamic(), React.lazy), которые не нужны сразу.

Типичные причины несовпадения

ПричинаПочему ломается
new Date(), Date.now()Время на сервере и в браузере разное
Math.random(), генерация idРазные значения при каждом рендере
window, localStorage, navigatorНа сервере их нет, ветка кода отличается
Форматирование дат и чиселРазные часовые пояса и локали
Невалидная вложенность HTMLНапример, <div> внутри <p> — браузер перестраивает разметку
Расширения браузераДобавляют атрибуты или элементы до старта React

Как исправить

1. Переносите браузерную логику в useEffect. Эффекты не выполняются на сервере, поэтому первый рендер совпадёт, а значение появится сразу после.

"use client";
import { useEffect, useState } from "react";

export function LocalTime() {
  const [time, setTime] = useState<string | null>(null);

  useEffect(() => {
    setTime(new Date().toLocaleTimeString());
  }, []);

  return <span>{time ?? "—"}</span>;
}

2. Используйте useId для идентификаторов. Он выдаёт одинаковые id на сервере и клиенте, в отличие от Math.random().

3. Фиксируйте часовой пояс и локаль. Передавайте их явно в Intl.DateTimeFormat или форматируйте дату на сервере и отдавайте готовую строку.

4. Отключайте SSR для чисто клиентских виджетов. Карты, редакторы, графики, зависящие от размера окна, можно загружать только в браузере — в Next.js через dynamic(() => import(...), { ssr: false }) внутри клиентского компонента.

5. Исправьте разметку. Проверьте, нет ли блочных элементов внутри <p>, вложенных <a> или <table> без <tbody>.

6. suppressHydrationWarning — только точечно. Атрибут подавляет предупреждение для одного элемента, например для метки времени. Это не исправление, а осознанное исключение.

Как найти источник ошибки

  • Читайте сообщение в консоли целиком: современный React показывает diff серверного и клиентского значения.
  • Откройте страницу в режиме инкогнито без расширений, чтобы исключить их влияние.
  • Сравните «исходный код страницы» (серверный HTML) с тем, что видно в инспекторе.
  • Ищите в проблемном компоненте Date, random, window и условия вроде typeof window !== "undefined" прямо в рендере.

Частые вопросы

Да. React может перерисовать часть дерева на клиенте, что даёт мерцание, потерю производительности, а иногда и рассинхрон интерфейса с состоянием. Такие ошибки стоит исправлять, а не игнорировать.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.