Domů
» Základní znalosti
»
Jak opravit chybu „Hydration failed because the initial UI does not match“
Jak opravit chybu „Hydration failed because the initial UI does not match“
Výsledek, kterého chcete dosáhnout, je snadno popsatelný: HTML vygenerované na serveru se musí shodovat s tím, co React vygeneruje při prvním vykreslení v prohlížeči. Pokud tomu tak je, React může připojit obsluhu událostí a zpřístupnit stránku pro interakci bez vyvolání chyby nesouladu hydratace, nahrazení podstromu nebo zobrazení neočekávaného vizuálního poskoku.
Hydratace je proces, při kterém React převezme HTML, které bylo již vykresleno na serveru, a v prohlížeči k němu připojí chování Reactu. Současná dokumentace hydrateRoot uvádí, že obsah vykreslený na klientovi má být identický s obsahem vykresleným na serveru a že nesoulady by měly být považovány za chyby.
Přesné znění chybové hlášky se v průběhu vydání Reactu a frameworků měnilo. Můžete narazit na starší zprávu, jako je „Hydration failed because the initial UI does not match what was rendered on the server“, nebo na novější zprávu vysvětlující, že strom vykreslený na serveru neodpovídal stromu na klientovi. Princip ladění zůstává stejný.
Kontext verze je důležitý. K 11. září 2026 oficiální web Reactu uvádí React 19.3 jako nejnovější verzi Reactu, zatímco aktuální dokumentace Next.js identifikuje Next.js 16.3.4 jako nejnovější vydání Next.js. Pokud tento článek čtete později, zkontrolujte stránku verzí Reactu a aktuální dokumentaci Next.js, protože dostupná API a chybové zprávy se mohou měnit.
Ilustrace generovaná AI: Začněte nalezením první komponenty uvedené v chybové hlášce hydratace a potvrzením, že problém nastává při novém načtení stránky. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Co se počítá jako úspěšná oprava?
Nesoudíte úspěch pouze podle toho, zda zmizí červené překrytí ve vývojovém prostředí. Dobrá oprava by měla splňovat několik kontrol:
Varování nebo chyba hydratace se již při čistém znovunačtení neobjevují.
Počáteční UI vykreslené na serveru a první vykreslení Reactu v prohlížeči představují stejný obsah a strukturu.
Ovlivněná komponenta zůstává po hydrataci interaktivní.
Nedochází k zjevnému blikání mezi hodnotami, pokud není tato změna záměrná a navržená.
Problém zůstává opraven i v produkčním buildu, nikoliv pouze ve vývojovém serveru.
Opravili jste příčinu, místo abyste skryli skutečný nesoulad pomocí možnosti potlačení varování.
Pokud varování zmizí, ale stránka nyní vykresluje důležitý obsah až po načtení JavaScriptu, mohla být chyba odstraněna, zatímco uživatelský zážitek se zhoršil. To může být rozumný kompromis pro widget fungující pouze v prohlížeči, ale automaticky to není nejlepší výsledek pro primární obsah stránky.
Krok 1: Reprodukovat nesoulad a najít nejmenší selhávající komponentu
Začněte tvrdým znovunačtením ve vývojovém prostředí a přečtěte si celou chybovou hlášku, včetně zásobníku komponent. Dokumentovaná chyba hydratace v Reactu 19 uvádí několik běžných příčin: rozvětvení server/klient, jako je typeof window !== 'undefined', měnící se hodnoty, jako je Date.now() nebo Math.random(), formátování dat závislé na locale, externí data, která se změnila bez snímku, neplatné vnoření HTML a rozšíření prohlížeče, která upravují DOM. Viz chyba Reactu 418.
Next.js uvádí podobný seznam ve své oficiální příručce o chybách hydratace, kde přidává API dostupná pouze v prohlížeči, jako je window a localStorage, konfiguraci CSS-in-JS a HTML upravené vrstvou Edge/CDN.
Ilustrace generovaná AI: Zúžte chybu na výraz, který může produkovat odlišnou hodnotu na serveru a v prohlížeči, jako je datum, náhodné číslo, locale nebo hodnota odvozená z prohlížeče. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Praktickou metodou izolace je dočasně nahradit podezřelé dynamické sekce deterministickým textem. Pokud chyba zmizí, obnovujte tyto sekce jednu po druhé. To je obvykle rychlejší než měnit globální nastavení vykreslování, než zjistíte, která komponenta je odpovědná.
Signál kvality
Můžete přejít k dalšímu kroku, když dokážete pojmenovat jak selhávající komponentu, tak hodnotu nebo strukturu, která se liší. „Stává se to někde v dashboardu“ je stále příliš obecné. „Časové razítko v StatusCard je generováno nezávisle na serveru a klientovi“ je akční.
Krok 2: Odstranit nedeterministické hodnoty z počátečního vykreslení
Deterministické vykreslování znamená, že stejné vstupy produkují stejné počáteční UI. Hodnoty, které se nezávisle mění mezi vykreslením na serveru a v prohlížeči, jsou častými zdroji nesouladu.
Zvažte tento problematický vzor:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
Server a prohlížeč mohou tento kód spustit v různých okamžicích a v různých localech nebo časových pásmech. Lepší řešení závisí na tom, co má stránka komunikovat.
Pokud časové razítko představuje data ze serveru, vypočítejte nebo načtěte je jednou na serveru a předejte stejnou serializovanou hodnotu klientovi:
Pokud hodnota skutečně závisí na prohlížeči uživatele, vykreslete nejprve stabilní zástupný symbol a aktualizujte jej po hydrataci.
Ilustrace generovaná AI: Stabilní počáteční hodnota se může čistě hydratovat a poté lze po namontování komponenty aplikovat obsah specifický pro prohlížeč. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
To funguje, protože server a první vykreslení na klientovi produkují stejný zástupný symbol. Dokumentace Reactu k useEffect popisuje tento dvoustupňový vzor pro vzácné případy, kdy se obsah na klientovi musí lišit od obsahu na serveru.
Kdy změnit přístup
Pokud je hodnota dostupná pouze v prohlížeči celým účelem komponenty – například editor obnovený z localStorage nebo widget, který nelze smysluplně vykreslit na serveru – vynucování vzoru zástupného symbolu a efektu v celé komponentě může přidat zbytečnou složitost. V takovém případě použijte záměrnou hranici pouze pro prohlížeč, místo abyste předstírali, že je komponenta vykreslitelná na serveru.
Krok 3: Nečtěte API dostupná pouze v prohlížeči během prvního serverově kompatibilního vykreslení
Běžným omylem v Next.js je domněnka, že přidání 'use client' zaručuje, že se komponenta vykresluje pouze v prohlížeči. To neplatí. Next.js vysvětluje, že Client Components jsou hranicí pro stav, efekty, obsluhu událostí a API prohlížeče, ale Client Components se stále mohou účastnit předvykreslování. Viz aktuální dokumentace use client.
Na serveru localStorage neexistuje. I rozvětvení, jako je typeof window !== 'undefined', může produkovat odlišné značkování při prvním vykreslení v prohlížeči, což React i Next.js dokumentují jako příčinu nesouladu hydratace.
Pro malé rozdíly přesuňte čtení z prohlížeče do Efektu. Pro komponentu, která by měla být v Next.js skutečně pouze pro prohlížeč, ji můžete dynamicky načíst s vypnutým SSR:
Ilustrace generovaná AI: Použijte hranici pouze pro klienta pro komponenty, které fundamentálně závisí na API prohlížeče, místo aby server a prohlížeč vykreslovaly různé stromy. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Next.js dokumentuje ssr: false pro Client Components ve své příručce líného načítání. Stejná příručka uvádí, že ssr: false není podporováno, pokud se pokusíte použít tuto možnost přímo v Server Component; přesuňte dynamický import do Client Component.
React 19.3: prvotřídní možnost pouze pro prohlížeč
React 19.3 zavedl API browser. Komponenta může uvnitř hranice Suspense zavolat use(browser()), aby tuto komponentu vyloučila ze serverového vykreslování. Server vykreslí fallback Suspense, zatímco komponenta se normálně vykreslí v prohlížeči. Viz reference API browser Reactu.
import { Suspense, use } from 'react';
import { browser } from 'react-dom';
function BrowserOnlyContent() {
use(browser('Requires browser APIs'));
return <ActualBrowserContent />;
}
export default function Example() {
return (
<Suspense fallback={<p>Loading...</p>}>
<BrowserOnlyContent />
</Suspense>
);
}
V aplikaci React Server Components React uvádí, že use(browser()) musí být volán z Client Component. Před přijetím této API také ověřte, zda váš framework a nainstalovaná verze Reactu tuto API vystavují.
Krok 4: Učinit data ze serveru a první data na klientovi stejným snímkem
Snímek je přesný stav dat použitý k vygenerování počátečního HTML. Hydratace se stává křehkou, pokud server vykreslí jednu verzi dat a klient okamžitě načte novější nebo jinak seřazenou verzi před dokončením hydratace.
Ilustrace generovaná AI: První vykreslení na klientovi by mělo spotřebovat stejný počáteční snímek dat, který vygeneroval HTML na serveru; pozdější aktualizace mohou nastat po hydrataci. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Například předpokládejme, že server vykreslí cenu 99 USD, ale klient okamžitě načte stejný produkt a získá 109 USD před svým prvním vykreslením. Problémem není, že se data změnila; měnící se data jsou normální. Problémem je, že dvě prostředí použila různé počáteční vstupy.
Silný vzor je:
Načíst počáteční data na serveru.
Vykreslit HTML z těchto dat.
Předat nebo serializovat stejná počáteční data do komponenty na klientovi.
Po hydrataci umožnit klientovi revalidaci a aktualizaci, pokud existují novější data.
Správná implementace závisí na modelu načítání dat vašeho frameworku, ale kritérium kvality zůstává stejné: HTML na serveru a první strom na klientovi by měly být založeny na stejném logickém stavu.
Kdy změnit přístup
Pokud je obsah inherentně real-time a zastaralý snímek ze serveru by uživatele mátl – například živý obchodní widget nebo rychle se měnící operační konzole – zvažte vykreslení stabilního obalu na serveru a načtení živé sekce na klientovi. To obětuje nějaký obsah vykreslený na serveru pro tuto oblast, ale může to být upřímnější než hydratace proti datům, která jsou zaručena ke změně.
Krok 5: Opravit neplatné HTML, než budete vinit React
Prohlížeče mají povolenost opravovat špatně tvarované nebo neplatně vnořené HTML. Tato oprava může vytvořit strukturu DOM, která se liší od struktury, kterou React očekává, i když JSX vypadalo vizuálně pravděpodobně.
Ilustrace generovaná AI: Zkontrolujte sémantické vnoření HTML, když se strom komponent zdá být deterministický, ale prohlížeč stále konstruuje jiný DOM. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Next.js explicitně uvádí příklady, jako je <div> uvnitř <p>, seznam uvnitř odstavce, vnořené odkazy a vnořená tlačítka, jako příčiny problémů s hydratací.
Například se vyhněte:
<p>
Intro text
<div>Details</div>
</p>
Místo toho použijte platnou strukturu:
<div>
<p>Intro text</p>
<div>Details</div>
</div>
Pokud značkování generuje knihovna komponent, prozkoumejte finální DOM, místo abyste předpokládali, že obalové prvky jsou platné. Pomoci může lint pravidlo nebo validátor HTML, ale skutečný DOM prohlížeče je to, co React hydratuje.
Krok 6: Vyloučit kód mimo komponentu
Pokud je vaše logika vykreslování deterministická a vaše HTML je platné, zkontrolujte, zda něco neupravuje HTML ze serveru před tím, než jej React hydratuje.
Oficiální dokumentace Next.js uvádí několik možností:
Rozšíření prohlížeče změní stránku před načtením Reactu.
Knihovna CSS-in-JS je nesprávně nakonfigurována pro serverové vykreslování.
Funkce Edge nebo CDN přepisuje nebo minifikuje odpověď HTML.
Na iOS může automatická detekce telefonních čísel, e-mailových adres, dat nebo adres v některých případech změnit text na odkazy.
Používejte kontrolovaná porovnání. Testujte v soukromém okně prohlížeče s vypnutými rozšířeními. Pokud chyba nastává pouze za CDN, porovnejte ji s odpovědí původního serveru. Pokud začala po přijetí knihovny pro stylování, postupujte podle oficiální konfigurace SSR této knihovny, místo abyste aplikovali obecný workaround pro hydrataci.
Signál kvality
Tuto třídu problémů jste izolovali, když se stejný build aplikace hydratuje správně v jednom kontrolovaném prostředí, ale selže po tom, co specifické rozšíření prohlížeče, proxy, transformace CDN nebo integrace změní HTML.
Krok 7: Použít suppressHydrationWarning pouze pro skutečně nevyhnutelný lokální rozdíl
React poskytuje suppressHydrationWarning={true} pro vzácné případy, kdy text nebo atributy jednoho prvku nemohou rozumně odpovídat, jako jsou určitá časová razítka.
To není obecný mechanismus opravy. Dokumentace Reactu ke běžným DOM props uvádí, že tato možnost funguje pouze do jedné úrovně hloubky a je určena jako úniková cesta. Příručka hydratace Next.js také varuje, že React nebude při použití této možnosti pokoušet o opravu nesouladu textového obsahu.
Použijte ji pouze tehdy, když platí všechno následující:
Rozdíl je očekávaný a lokalizovaný.
Nesoulad neznamená nesprávný stav aplikace.
Okolní struktura je stabilní.
Vědomě jste přijali, že počáteční hodnota na serveru a hodnota v prohlížeči se liší.
Pokud přidání této vlastnosti způsobí zmizení desítek varování, je to důvod k dalšímu šetření, nikoliv znak toho, že je základní problém vyřešen.
Krok 8: Ověřit opravu ve vývoji a produkci
Ilustrace generovaná AI: Po změně kódu ověřte čisté znovunačtení, správnou interaktivitu a produkční build, místo abyste spoléhali pouze na překrytí ve vývojovém prostředí. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Chování ve vývojovém prostředí se může lišit od optimalizovaného produkčního buildu. Po zmizení chyby lokálně proveďte kontrolu ve stylu produkce pro váš framework. Pro typický projekt Next.js to často znamená sestavení a spuštění aplikace pomocí běžných příkazů správce balíčků, následované novými navigacemi a znovunačteními.
Použijte tento kontrolní seznam ověření:
Kontrola
Dobré znamení
Pokud selže
Nové znovunačtení
Žádná chyba hydratace v konzoli
Znovu zkontrolujte nejranější lišící se komponentu
Počáteční vizuální stav
Žádné nechtěné blikání nebo nahrazení
Učiňte počáteční stav deterministickým
Interakce
Tlačítka, formuláře, nabídky a stav fungují normálně
Potvrďte, že se komponenta stále hydratuje a obsluha událostí se připojuje
Produkční build
Stejný správný výsledek jako ve vývoji
Prošetřete chování dat, CDN, CSS nebo optimalizace specifické pro produkci
Rozšíření vypnuta
Výsledek je nezměněn
Identifikujte chování rozšíření upravujících DOM
Pokud přímo vlastníte vstupní bod React SSR místo použití frameworku, hydrateRoot také podporuje zpětná volání pro chyby, jako je onRecoverableError, která mohou pomoci s logováním v produkci. Uživatelé frameworků by obecně neměli nahrazovat vstupní bod hydratace frameworku pouze kvůli přidání vlastního zpracování.
Kdy zkusit jinou strategii vykreslování
Ilustrace generovaná AI: Změňte strategii, když komponenta fundamentálně nemůže vygenerovat smysluplné HTML na serveru, ale udržujte hranici pouze pro klienta co nejmenší, jak je praktické. Toto není skutečný snímek obrazovky prohlížeče, Reactu nebo Next.js; jako zdroj pravdy použijte ověřené odkazy na kód a dokumentaci v článku.
Někdy není nejlepší opravou nutit komponentu do SSR. Zvažte jinou strategii vykreslování, když:
Je komponenta postavena kolem window, canvas, WebGL, měření prohlížeče nebo jiného API dostupného pouze v prohlížeči.
Widget třetí strany oficiálně nepodporuje SSR.
Smysluplný obsah komponenty závisí entirely na stavu lokálním pro zařízení, jako je localStorage.
Real-time data se mění tak rychle, že shoda se snímkem ze serveru má malou hodnotu.
V takových případech může být cílená hranice pouze pro klienta čistší. Klíčovým slovem je cílená. Vypnutí SSR pro celou stránku kvůli jednomu grafu nebo editoru může zbytečně obětovat užitečný obsah vykreslený na serveru, chování při načítání a další výhody.
Běžné opravy, které vypadají úspěšně, ale nejsou
Zkratka
Proč je neúplná
Lepší kritérium
Přidat 'use client' všude
Client Components mohou být stále předvykreslovány v Next.js
Přesuňte logiku pouze pro prohlížeč po hydrataci nebo ji záměrně izolujte
Zabalit logiku vykreslování do typeof window !== 'undefined'
Rozvětvení samo o sobě může vytvořit odlišné značkování prvního vykreslení
Udržujte první vykreslení identické
Používat suppressHydrationWarning široce
Skryje varování místo toho, aby uvádělo do souladu stav aplikace
Použijte pouze pro očekávaný, lokální, nevyhnutelný nesoulad
Vypnout SSR pro celou stránku
Může odstranit příznak odstraněním hydratace pro příliš mnoho UI
Použijte nejmenší praktickou hranici pouze pro klienta
Testovat pouze klientskou navigaci
Nesoulad se může objevit pouze při přímém požadavku nebo tvrdém znovunačtení
Testujte nová načtení stránek vykreslených na serveru
Meze těchto oprav
Chyba hydratace vám říká, že se vykreslování na serveru a klientovi rozcházejí; nedokazuje proč. Stejný příznak může pocházet z logiky aplikace, mutace prohlížeče, knihovny, CDN, špatně tvarovaného HTML nebo měnících se dat. Neexistuje žádný jediný úryvek kódu, který by bezpečně opravil všechny tyto případy.
Také odstranění varování hydratace nezaručuje správnost jinde. Komponenta pouze pro klienta může mít stále datové závody. Deterministické první vykreslení může stále zobrazovat zastaralá data po hydrataci. Platný DOM může stále obsahovat problémy s přístupností. Považujte hydrataci za jednu bránu kvality, nikoliv za jedinou.
Nové API browser v Reactu 19.3 také neznamená, že by každý framework měl okamžitě nahradit svůj zavedený vzor pouze pro prohlížeč. Integrace frameworku a nainstalované verze jsou důležité. Pokud je váš projekt na starší verzi Reactu nebo Next.js, postupujte podle dokumentace pro tuto verzi, místo abyste slepě kopírovali novější API.
Spolehlivé pořadí rozhodování
Najděte nejmenší komponentu, která se neshoduje.
Zkontrolujte měnící se hodnoty, jako jsou data, náhodná čísla, formátování locale a data načtená dvakrát.
Odstraňte API dostupná pouze v prohlížeči z prvního serverově kompatibilního vykreslení.
Ujistěte se, že server a první vykreslení na klientovi používají stejný snímek dat.
Ověřte strukturu HTML.
Vyloučte rozšíření, konfiguraci SSR CSS-in-JS a přepisování CDN/Edge.
Použijte Efekt, cílené vykreslování pouze pro klienta nebo React 19.3 use(browser()) pouze tehdy, když obsah skutečně závisí na prohlížeči.
Vyhraďte suppressHydrationWarning pro malé, záměrné nesoulady.
Ověřte novým znovunačtením a produkčním buildem.
Trvalá oprava není „nechat React přestat stěžovat“. Je to explicitní stanovení smlouvy o počátečním vykreslování: server a prohlížeč by se měli shodnout na prvním UI, nebo by měla být sekce pouze pro prohlížeč záměrně izolována, aby React nebyl žádán o hydrataci značkování, které by nikdy nemohlo odpovídat.