Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке помилка невідповідності гідрації (hydration mismatch) і як її виправити?

Під час гідрації Vue очікує, що DOM, отриманий із сервера, точно відповідає тому, що відрендерив би клієнт з тими самими даними. Якщо ні - у консолі Hydration mismatch, а Vue виправляє розбіжність, перебудовуючи частину DOM. Це повільно, а в продакшені може лишити неправильний вміст.

Типові причини:

1. Дані, що відрізняються на сервері й клієнті:

<span>{{ new Date().toLocaleTimeString() }}</span>   <!-- час сервера ≠ час браузера -->
<span>{{ Math.random() }}</span>
<p>{{ formatDate(order.createdAt) }}</p>          <!-- різні часові пояси -->

2. Код, що залежить від браузера:

<div v-if="window.innerWidth > 768">...</div>      <!-- на сервері window немає -->
<p>{{ localStorage.getItem('name') }}</p>

3. Невалідна вкладеність HTML. <div> всередині <p>, <tr> без <tbody> - браузер «виправляє» розмітку при розборі, і DOM уже не відповідає серверному HTML.

4. Сторонні скрипти й розширення браузера, що змінюють DOM до гідрації.

5. Генеровані id, які на сервері й клієнті виходять різними (лічильник, Math.random()).

Як виправляти:

  • значення, що мають бути лише на клієнті, - встановлювати в onMounted (він не виконується на сервері):
const now = ref<string | null>(null)
onMounted(() => { now.value = new Date().toLocaleTimeString() })
  • детерміновані дані: форматування дат з явним часовим поясом (Intl.DateTimeFormat('uk', { timeZone: 'Europe/Kyiv' })), а не поясом середовища;
  • useId() (Vue 3.5) для id, стабільних між сервером і клієнтом;
  • клієнтські компоненти - рендерити лише в браузері (<ClientOnly> у Nuxt чи власна обгортка з прапорцем, встановленим в onMounted);
  • валідна розмітка - перевіряється валідатором HTML.

Свідома розбіжність. Якщо значення має відрізнятися (час, локальна дата), Vue 3.5 дозволяє придушити попередження атрибутом:

<span data-allow-mismatch="text">{{ localTime }}</span>

Значення атрибута обмежує тип розбіжності: text, children, class, style, attribute. Це для точкових випадків, а не спосіб приховати справжні баги.

Діагностика: у режимі розробки попередження показує, який саме вузол не збігся. Для продакшен-збірки детальні повідомлення вмикаються прапорцем __VUE_PROD_HYDRATION_MISMATCH_DETAILS__.

Докладніше в документації: SSR: невідповідність гідрації

Схожі питання