Начало
» Основни познания
»
Как да поправите грешката „Хидратацията не успя, защото първоначалният интерфейс не съвпада“
Как да поправите грешката „Хидратацията не успя, защото първоначалният интерфейс не съвпада“
Резултатът, който искате, е лесен за описание: HTML кодът, генериран на сървъра, трябва да съвпада с това, което React генерира при първото изобразяване в браузъра. Когато това е вярно, React може да прикачи обработчици на събития и да направи страницата интерактивна, без да хвърли грешка за несъвпадение при хидратация, да замени поддърво или да покаже неочакван визуален скок.
Хидратацията е процесът, при който React поема HTML, вече изобразен на сървъра, и прикрепя React поведение към него в браузъра. Текущата документация на React за hydrateRoot посочва, че съдържанието, изобразено от клиента, се очаква да бъде идентично със съдържанието, изобразено от сървъра, и че несъвпаденията трябва да се третират като бъгове.
Точният текст на грешката се е променял в различните версии на React и рамките. Може да видите по-старо съобщение като "Хидратацията не успя, защото първоначалният интерфейс не съвпада с това, което е изобразено на сървъра", или по-ново съобщение, обясняващо, че дървото, изобразено от сървъра, не съвпада с това на клиента. Принципът за дебъгване остава същият.
Контекстът на версията е важен. Към 11 септември 2026 г. официалният сайт на React посочва React 19.3 като най-новата версия на React, докато текущата документация на Next.js идентифицира Next.js 16.3.4 като най-новото издание на Next.js. Проверете страницата с версии на React и текущата документация на Next.js, ако четете това по-късно, тъй като наличните API и съобщения за грешки могат да се променят.
Илюстрация, генерирана от AI: Започнете, като откриете първия компонент, споменат в грешката при хидратация, и потвърдите, че проблемът възниква при ново зареждане на страницата. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Какво се счита за успешно поправяне?
Не преценявайте успеха само по това дали червеният оверлей за разработка изчезва. Едно добро поправяне трябва да отговаря на няколко проверки:
Предупреждението или грешката при хидратация вече не се появява при чисто презареждане.
Първоначалният интерфейс, изобразен от сървъра, и първото изобразяване на React в браузъра представляват едно и също съдържание и структура.
Засегнатият компонент остава интерактивен след хидратацията.
Няма очевидна мигане от една стойност към друга, освен ако тази промяна не е умишлена и проектирана.
Проблемът остава поправен в производствена версия, а не само в сървъра за разработка.
Вие сте коригирали причината, вместо да скриете реално несъвпадение с опция за потискане на предупреждения.
Ако предупреждението изчезне, но страницата вече изобразява важно съдържание само след зареждането на JavaScript, грешката може да е изчезнала, докато потребителското изживяване се е влошило. Това може да е разумен компромис за уиджет, работещ само в браузъра, но не е автоматично най-добрият резултат за основното съдържание на страницата.
Стъпка 1: Възпроизведете несъвпадението и намерете най-малкия отказващ компонент
Започнете с твърдо презареждане в среда за разработка и прочетете цялата грешка, включително стека на компонентите. Документираната грешка при хидратация на React 19 изброява няколко чести причини: разклонения сървър/клиент като typeof window !== 'undefined', променящи се стойности като Date.now() или Math.random(), форматиране на дати, зависещо от локалния език, външни данни, които са се променили без снимка (snapshot), невалидно вгнезждане на HTML и разширения на браузъра, които модифицират DOM. Вижте Грешка 418 на React.
Next.js дава подобен списък в своето официално ръководство за грешки при хидратация, добавяйки API, достъпни само в браузъра, като window и localStorage, конфигурация на CSS-in-JS и HTML, модифициран от слой Edge/CDN.
Илюстрация, генерирана от AI: Стеснете грешката до израза, който може да произведе различна стойност на сървъра и в браузъра, като дата, случайно число, локален език или стойност, получена от браузъра. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Практически метод за изолиране е временно да замените подозрителните динамични секции с детерминистичен текст. Ако грешката изчезне, възстановете тези секции една по една. Това обикновено е по-бързо от промяната на глобалните настройки за изобразяване, преди да знаете кой компонент е отговорен.
Сигнал за качество
Готови сте да продължите, когато можете да назовете както отказващия компонент, така и стойността или структурата, които се различават. „Случва се някъде в таблото за управление“ все още е твърде широко. „Времевият печат в StatusCard се генерира независимо на сървъра и клиента“ е действие, което може да се предприеме.
Стъпка 2: Премахнете недетерминистичните стойности от първоначалното изобразяване
Детерминистичното изобразяване означава, че едни и същи входни данни произвеждат един и същ първоначален интерфейс. Стойностите, които се променят независимо между изобразяването на сървъра и изобразяването в браузъра, са чести източници на несъвпадения.
Помислете за този проблематичен модел:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
Сървърът и браузърът може да изпълнят този код в различни моменти и в различни локални езици или часови зони. По-доброто решение зависи от това какво трябва да комуникира страницата.
Ако времевият печат представлява данни от сървъра, изчислете или извлечете го веднъж на сървъра и предайте същата сериализирана стойност на клиента:
Ако стойността наистина зависи от браузъра на потребителя, изобразете стабилен резервен елемент (placeholder) първо и го актуализирайте след хидратацията.
Илюстрация, генерирана от AI: Стабилна първоначална стойност може да се хидратира чисто, след което съдържание, специфично за браузъра, може да бъде приложено, след като компонентът се монтират. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Това работи, защото сървърът и първото клиентско изобразяване произвеждат един и същ резервен елемент. Документацията на React за useEffect описва този двуетапен модел за редките случаи, когато клиентското съдържание трябва да се различава от сървърното съдържание.
Кога да промените подхода
Ако стойността, достъпна само в браузъра, е цялата цел на компонента – например редактор, възстановен от localStorage, или уиджет, който не може да се изобрази смислено на сървъра – налагането на модел с резервен елемент и ефект в целия компонент може да добави ненужна сложност. В този случай използвайте умишлена граница само за браузъра, вместо да се правите, че компонентът може да се изобразява от сървъра.
Стъпка 3: Не четете API, достъпни само в браузъра, по време на първото съвместимо със сървъра изобразяване
Често погрешно схващане в Next.js е, че добавянето на 'use client' гарантира, че компонентът се изобразява само в браузъра. Това не е вярно. Next.js обяснява, че Client Components са границата за състояние, ефекти, обработчици на събития и API на браузъра, но Client Components все пак могат да участват в предварително изобразяване (prerendering). Вижте текущата документация за use client.
На сървъра localStorage не съществува. Дори разклонение като typeof window !== 'undefined' може да произведе различен маркиращ код (markup) при първото изобразяване в браузъра, което както React, така и Next.js документират като причина за несъвпадение при хидратация.
За малки разлики преместете четенето от браузъра в Ефект. За компонент, който наистина трябва да е само за браузъра в Next.js, можете да го заредите динамично с деактивирано SSR:
Илюстрация, генерирана от AI: Използвайте граница само за клиента за компоненти, които фундаментално зависят от API на браузъра, вместо да позволите на сървъра и браузъра да изобразяват различни дървета. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Next.js документира ssr: false за Client Components в своето ръководство за мързеливо зареждане. Същото ръководство посочва, че ssr: false не се поддържа, когато се опитате да използвате тази опция директно в Server Component; преместете динамичния импорт в Client Component.
React 19.3: първокласна опция само за браузъра
React 19.3 представи API browser. Компонент може да извика use(browser()) вътре в Suspense граница, за да изключи този компонент от сървърно изобразяване. Сървърът изобразява резервния елемент на Suspense, докато компонентът се изобразява нормално в браузъра. Вижте референцията за browser API на React.
import { Suspense, use } from 'react';
import { browser } from 'react-dom';
function BrowserOnlyContent() {
use(browser('Изисква API на браузъра'));
return <ActualBrowserContent />;
}
export default function Example() {
return (
<Suspense fallback={<p>Зареждане...</p>}>
<BrowserOnlyContent />
</Suspense>
);
}
В приложение с React Server Components React посочва, че use(browser()) трябва да бъде извикан от Client Component. Също така проверете дали вашата рамка и инсталираната версия на React предоставят това API, преди да го внедрите.
Стъпка 4: Направете данните от сървъра и първите данни на клиента една и съща снимка (snapshot)
Снимка (snapshot) е точното състояние на данните, използвано за производство на първоначалния HTML. Хидратацията става крехка, ако сървърът изобразява една версия на данните, а клиентът веднага прочете по-нова или различно подредена версия, преди хидратацията да завърши.
Илюстрация, генерирана от AI: Първото клиентско изобразяване трябва да консумира същата първоначална снимка на данните, която е произвела HTML от сървъра; по-късни актуализации могат да настъпят след хидратацията. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Например, представете си, че сървърът изобразява цена от $99, но клиентът веднага извлича същия продукт и получава $109 преди първото си изобразяване. Проблемът не е в това, че данните са се променили; промяната на данните е нормална. Проблемът е, че двете среди са използвали различни първоначални входни данни.
Силен модел е:
Извлечете първоначалните данни на сървъра.
Изобразете HTML от тези данни.
Предайте или сериализирайте същите първоначални данни в клиентския компонент.
След хидратацията позволете на клиента да ревалидира и актуализира, ако съществуват по-нови данни.
Правилната реализация зависи от модела за извличане на данни на вашата рамка, но критерият за качество остава същият: HTML от сървъра и първото клиентско дърво трябва да се базират на едно и също логическо състояние.
Кога да промените подхода
Ако съдържанието е по своята същност в реално време и остаряла снимка от сървъра би подвела потребителите – например уиджет за търговия на живо или бързо променяща се конзола за операции – помислете за изобразяване на стабилна обвивка на сървъра и зареждане на живата секция от клиента. Това жертва малко сървърно изобразено съдържание за този регион, но може да е по-честно от хидратирането срещу данни, за които е гарантирано, че ще се променят.
Стъпка 5: Поправете невалидния HTML, преди да обвините React
Браузърите имат право да коригират неправилно или невалидно вгнезден HTML. Тази корекция може да произведе DOM структура, която се различава от структурата, която React очаква, дори когато JSX изглеждаше визуално правдоподобно.
Илюстрация, генерирана от AI: Проверете семантичното вгнезждане на HTML, когато дървото на компонентите изглежда детерминистично, но браузърът все пак конструира различен DOM. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Next.js изрично изброява примери като <div> вътре в <p>, списък вътре в параграф, вгнездени анкори и вгнездени бутони като причини за проблеми с хидратацията.
Ако библиотека с компоненти генерира маркиращия код, инспектирайте крайния DOM, вместо да приемате, че обвиващите елементи са валидни. Правило за lint или валидатор на HTML може да помогне, но действителният DOM на браузъра е този, който React хидратира.
Стъпка 6: Изключете кода извън компонента
Ако логиката ви за изобразяване е детерминистична и HTML е валиден, проверете дали нещо не модифицира HTML от сървъра, преди React да го хидратира.
Официалната документация на Next.js посочва няколко възможности:
Разширение на браузъра променя страницата, преди React да се зареди.
Библиотека CSS-in-JS е конфигурирана неправилно за сървърно изобразяване.
Функция на Edge или CDN презаписва или минифицира HTML отговора.
На iOS автоматичното откриване на телефонни номера, имейл адреси, дати или адреси може да промени текста в линкове в някои случаи.
Използвайте контролирани сравнения. Тествайте в частен прозорец на браузъра с деактивирани разширения. Ако грешката възниква само зад CDN, сравнете с отговора от източника. Ако е започнала след внедряване на библиотека за стилизиране, следвайте официалната SSR конфигурация на тази библиотека, вместо да прилагате общ заобикалящ път за хидратация.
Сигнал за качество
Изолирали сте този клас проблеми, когато едно и също приложение се хидратира правилно в една контролирана среда, но се проваля след като конкретно разширение на браузъра, прокси, CDN трансформация или интеграция промени HTML.
Стъпка 7: Използвайте suppressHydrationWarning само за наистина неизбежна локална разлика
React предоставя suppressHydrationWarning={true} за редки случаи, когато текстът или атрибутите на един елемент не могат разумно да съвпаднат, като например определени времеви печати.
Това не е общ механизъм за поправяне. Документацията на React за общи DOM пропс посочва, че опцията работи само на едно ниво дълбочина и е предназначена като аварийен изход. Ръководството за хидратация на Next.js също предупреждава, че React няма да се опита да поправи несъвпадащо текстово съдържание, когато тази опция е използвана.
Използвайте я само когато всички тези условия са изпълнени:
Разликата е очаквана и локализирана.
Несъвпадението не представлява неправилно състояние на приложението.
Околната структура е стабилна.
Вие сте съзнателно приели, че първоначалната стойност на сървъра и стойността в браузъра се различават.
Ако добавянето на пропът кара десетки предупреждения да изчезнат, това е причина за по-нататъшно разследване, а не знак, че основният проблем е решен.
Стъпка 8: Потвърдете поправката в среда за разработка и производство
Илюстрация, генерирана от AI: След промяна на кода, потвърдете чисто презареждане, правилна интерактивност и производствена версия, вместо да разчитате само на оверлея за разработка. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Поведението при разработка може да се различава от оптимизирана производствена версия. След като грешката изчезне локално, извършете проверка в стил производство за вашата рамка. За типичен проект с Next.js това често означава да изградите и стартирате приложението с обичайните си команди за мениджъра на пакети, след което да извършите нови навигации и презареждания.
Използвайте този списък за проверка:
Проверка
Добър знак
Ако се провали
Ново презареждане
Няма грешка при хидратация в конзолата
Проверете отново най-ранния различаващ се компонент
Първоначално визуално състояние
Няма непреднамерено мигане или заместване
Направете първоначалното състояние детерминистично
Взаимодействия
Бутоните, формите, менютата и състоянието работят нормално
Потвърдете, че компонентът все още се хидратира и обработчиците на събития се прикачат
Производствена версия
Същият правилен резултат като при разработка
Разследвайте данни, CDN, CSS или поведение на оптимизация, специфични за производство
Деактивирани разширения
Резултатът е непроменен
Идентифицирайте поведението на разширение, модифициращо DOM
Ако директно притежавате точката за вход на React SSR, вместо да използвате рамка, hydrateRoot също поддържа обратни извиквания за грешки като onRecoverableError, което може да помогне за логирането в производство. Потребителите на рамки обикновено не трябва да заместват точката за вход за хидратация на рамката, само за да добавят персонализирана обработка.
Кога да опитате различна стратегия за изобразяване
Илюстрация, генерирана от AI: Променете стратегията, когато компонент фундаментално не може да произведе смислен HTML от сървъра, но запазете границата само за клиента толкова малка, колкото е практически възможно. Това не е реална снимка на екрана на браузър, React или Next.js; използвайте проверените кодове и връзки към документацията в статията като източник на истина.
Понякога най-доброто поправяне не е да принудите компонент в SSR. Помислете за различна стратегия за изобразяване, когато:
Компонентът е построен около window, canvas, WebGL, измервания на браузъра или друго API, достъпно само в браузъра.
>Трета страна уиджет официално не поддържа SSR.
Смисленото съдържание на компонента зависи изцяло от локално състояние на устройството, като localStorage.
Данните в реално време се променят толкова бързо, че съвпадането със снимка от сървъра има малка стойност.
В тези случаи целева граница само за клиента може да е по-чиста. Ключовата дума е целева. Деактивирането на SSR за цяла страница, за да се побере една графика или редактор, може ненужно да жертва полезно сървърно изобразено съдържание, поведение при зареждане и други предимства.
Чести поправки, които изглеждат успешни, но не са
Преки път
Защо е непълно
По-добър критерий
Добавете 'use client' навсякъде
Client Components все пак могат да бъдат предварително изобразени в Next.js
Преместете логиката, достъпна само в браузъра, след хидратацията или я изолирайте умишлено
Обвийте логиката за изобразяване в typeof window !== 'undefined'
Самото разклонение може да създаде различен маркиращ код при първото изобразяване
Запазете първото изобразяване идентично
Използвайте suppressHydrationWarning широко
То скрива предупреждение, вместо да помири състоянието на приложението
Използвайте само за очаквано, локално, неизбежно несъвпадение
Деактивирайте SSR за цялата страница
Може да премахне симптома, като премахне хидратацията за твърде много UI
Използвайте най-малката практична граница само за клиента
Тествайте само клиентска навигация
Несъвпадение може да се появи само при директна заявка или твърдо презареждане
Тествайте нови зареждания на страници, изобразени от сървъра
Ограничения на тези поправки
Грешката при хидратация ви казва, че изобразяването на сървъра и клиента са се разминали; тя не доказва защо. Същият симптом може да идва от логиката на приложението, мутация на браузъра, библиотека, CDN, невалиден HTML или променящи се данни. Няма един код, който безопасно да поправи всички тези случаи.
Също така, премахването на предупрежденията за хидратация не гарантира правилност другаде. Компонент, работещ само в клиента, все пак може да има състезания на данни (data races). Детерминистично първо изобразяване все пак може да покаже остарели данни след хидратация. Валиден DOM все пак може да съдържа проблеми с достъпността. Третирайте хидратацията като една врата за качество, а не като единствената.
Новото API browser на React 19.3 също не означава, че всяка рамка трябва незабавно да замени установения си модел само за браузъра. Интеграцията на рамката и инсталираните версии имат значение. Ако проектът ви е на по-стара версия на React или Next.js, следвайте документацията за тази версия, вместо сляпо да копирате по-ново API.
Надежден ред за вземане на решения
Открийте най-малкия компонент, който не съвпада.
Проверете за променящи се стойности като дати, случайни числа, форматиране на локален език и данни, извлечени два пъти.
Премахнете API, достъпни само в браузъра, от първото съвместимо със сървъра изобразяване.
Уверете се, че сървърът и първото клиентско изобразяване използват една и съща снимка на данните.
Валидирайте HTML структурата.
Изключете разширения, SSR конфигурация на CSS-in-JS и презаписване от CDN/Edge.
Използвайте Ефект, целево клиентско изобразяване или React 19.3 use(browser()) само когато съдържанието наистина зависи от браузъра.
Запазете suppressHydrationWarning за малки, умишлени несъвпадения.
Потвърдете с ново презареждане и производствена версия.
Трайната поправка не е „карайте React да спре да се оплаква“. Тя е да направите договора за първоначално изобразяване явен: сървърът и браузърът трябва да се съгласят за първия UI, или секцията, работеща само в браузъра, трябва да бъде умишлено изолирана, така че React да не бъде помолен да хидратира маркиращ код, който никога не би могъл да съвпадне.