0Pricing
React Academy · Урок

Ошибки гидратации: причины и исправления

Находите несоответствия между HTML сервера и клиента и исправляйте их с помощью suppressHydrationWarning.

«Ошибки гидратации: причины и исправления» — бесплатный урок React Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.

Что такое ошибка гидратации

Ошибка гидратации возникает, когда HTML, отрисованный React на сервере, не совпадает с виртуальным DOM, который React ожидает на клиенте. React выводит предупреждение и заново отрисовывает компонент с нуля, вызывая вспышку.

Распространённая причина 1: случайные значения

Использование Math.random(), Date.now() или crypto.randomUUID() во время отрисовки создаёт разные значения на сервере и клиенте.

// Bad — different on server vs client:
<div id={Math.random().toString()}>...</div>

// Fix — use useId() (stable across server/client):
import { useId } from 'react';
function Component() {
  const id = useId();
  return <div id={id}>...</div>;
}

Распространённая причина 2: API только для браузера

Чтение localStorage, window.innerWidth или navigator во время отрисовки приводит к сбою на сервере или создаёт разные значения.

// Bad — localStorage doesn't exist on server:
<div>{localStorage.getItem('theme')}</div>

// Fix — read in useEffect (client-only):
const [theme, setTheme] = useState('light');
useEffect(() => {
  setTheme(localStorage.getItem('theme') ?? 'light');
}, []);

Распространённая причина 3: форматирование даты и времени

Форматирование даты с учётом локали возвращает разные строки на сервере (локаль UTC/Node) и на клиенте (локаль браузера).

// Risky — locale may differ:
<time>{new Date().toLocaleDateString()}</time>

// Fix — use a consistent locale:
<time>{new Date().toLocaleDateString('en-US', { timeZone: 'UTC' })}</time>

Распространённая причина 4: недопустимая вложенность HTML

React создаёт HTML клиента на основе виртуального DOM, но недопустимая вложенность HTML (например, <p> внутри <p>) заставляет браузеры по-разному перестраивать DOM, что приводит к несоответствиям.

// Bad — browser auto-closes the nested <p>:
<p>Outer <p>Inner</p> text</p>

// Fix — use <div> or correct semantic elements:
<div>Outer <p>Inner</p> text</div>

Распространённая причина 5: условная отрисовка на основе состояния

Компоненты, которые отрисовываются по-разному в зависимости от состояния, доступного только на клиенте (например, аутентификации пользователя или ширины экрана), не совпадают, потому что сервер выполняет отрисовку без этого состояния.

// Bad — server renders 'Guest', client re-renders 'Alice' immediately:
<h1>{user?.name ?? 'Guest'}</h1>

// Fix — use a mounted guard to defer client-only rendering:
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return <h1>Guest</h1>; // match server output

suppressHydrationWarning

Используйте suppressHydrationWarning на элементах, где несоответствия намеренны (например, для временных меток, форматируемых на клиенте). Это подавляет предупреждение только для данного элемента.

<time suppressHydrationWarning dateTime={isoDate}>
  {new Date(isoDate).toLocaleString()}
</time>

Динамический импорт с ssr: false

В Next.js используйте dynamic(fn, { ssr: false }), чтобы полностью запретить отрисовку компонента на сервере — это устраняет несоответствия гидратации для компонентов, работающих только на клиенте.

import dynamic from 'next/dynamic';

const ClientOnlyChart = dynamic(() => import('./Chart'), { ssr: false });

export default function Dashboard() {
  return <ClientOnlyChart />; // only renders in the browser
}

Отладка ошибок гидратации

В режиме разработки React 18 выводит подробные сообщения об ошибках гидратации с указанием точного несоответствия узлов DOM. Используйте браузерные DevTools, чтобы сравнить HTML с сервера и дерево React.

useId для стабильных идентификаторов

useId() создаёт стабильные уникальные идентификаторы, одинаковые при отрисовке на сервере и клиенте. Используйте его для пар id/htmlFor и атрибутов ARIA.

function FormInput({ label }: { label: string }) {
  const id = useId();
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input id={id} />
    </div>
  );
}

Тестирование ошибок гидратации

Запустите приложение Next.js в режиме разработки (npm run dev) и следите за консолью браузера. Несоответствия гидратации появляются в виде красных предупреждений с трассировками стека компонентов.

Проверка знаний

Как лучше всего исправить компонент, который отрисовывается по-разному на сервере и клиенте из-за чтения данных из localStorage?

Итоги

Несоответствия гидратации возникают из-за случайных значений, API только для браузера, форматирования с учётом локали, недопустимой вложенности HTML и условной отрисовки только на клиенте. Исправляйте их с помощью useId(), используйте useEffect для состояния только на клиенте, suppressHydrationWarning для намеренных различий и dynamic({ ssr: false }) для компонентов, работающих только на клиенте.

Часто задаваемые вопросы

Урок «Ошибки гидратации: причины и исправления» бесплатный?

Да — полный текст урока «Ошибки гидратации: причины и исправления» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.

Чему я научусь в уроке «Ошибки гидратации: причины и исправления»?

Находите несоответствия между HTML сервера и клиента и исправляйте их с помощью suppressHydrationWarning. Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать React Academy?

Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Ошибки гидратации: причины и исправления»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке React Academy?

Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Как работает SSR React изнутри
  2. Ошибки гидратации: причины и исправления
  3. Выборочная гидратация и потоковая передача HTML
  4. Паттерн архитектуры островов
← Назад к React Academy