Kezdőlap
» Alap tudás
»
Hogyan javítsd ki a „Hydration failed because the initial UI does not match” hibát
Hogyan javítsd ki a „Hydration failed because the initial UI does not match” hibát
A kívánt eredmény egyszerűen leírható: a szerveren generált HTML-nek meg kell egyeznie azzal, amit a React a böngésző első renderelésekor előállít. Ha ez teljesül, a React hozzáadhatja az eseménykezelőket és interaktívvá teheti az oldalt anélkül, hogy hidratálási eltérést dobna, alréteget cserélne le, vagy váratlan vizuális ugrást mutatna.
A hidratálás az a folyamat, amely során a React a szerveren már legenerált HTML-hez csatolja a React viselkedését a böngészőben. A React aktuális hydrateRoot dokumentációja kimondja, hogy a kliensoldalon renderelt tartalomnak azonosnak kell lennie a szerveroldalon renderelt tartalommal, és az eltéréseket hibaként kell kezelni.
A hibaüzenet pontos szövegezése változott a React és a keretrendszerek különböző kiadásaiban. Láthatsz egy régebbi üzenetet, mint például az "Hydration failed because the initial UI does not match what was rendered on the server", vagy egy újabb üzenetet, amely azt magyarázza, hogy a szerveroldali fa nem egyezett meg a kliensoldali fával. A hibakeresési elv ugyanaz marad.
A verziókontextus fontos. 2026. szeptember 11-én a hivatalos React oldal a React 19.3-at tünteti fel a legújabb React verzióként, míg a jelenlegi Next.js dokumentáció a Next.js 16.3.4-et jelöli meg a legújabb Next.js kiadásként. Ellenőrizd a React verzióoldalát és a jelenlegi Next.js dokumentációt, ha később olvasod ezt, mivel a elérhető API-k és hibaüzenetek változhatnak.
AI-generált illusztráció: Kezd azzal, hogy megtalálod a hidratálási hibában megnevezett első komponenst, és megerősíted, hogy a probléma friss oldalbetöltéskor jelentkezik. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
Mi számít sikeres javításnak?
Ne csak azt ítéld meg, hogy eltűnt-e a piros fejlesztői átfedés. Egy jó javításnak több ellenőrzésnek is meg kell felelnie:
A hidratálási figyelmeztetés vagy hiba többé nem jelenik meg tiszta újratöltéskor.
A kezdeti szerveroldali UI és a böngésző első React renderelése ugyanazt a tartalmat és struktúrát képviseli.
A érintett komponens interaktív marad a hidratálás után.
Nincs nyilvánvaló villanás az egyik értékről a másikra, hacsak ez a változás nem szándékos és tervezett.
A probléma megoldva marad egy éles (production) buildben is, nem csak a fejlesztői szerveren.
Az okot javítottad ki, ahelyett, hogy egy figyelmeztetés-elnyomási opcióval elrejtenéd a valódi eltérést.
Ha a figyelmeztetés eltűnik, de az oldal fontos tartalmát csak a JavaScript betöltése után jeleníti meg, a hiba eltűnhetett, miközben a felhasználói élmény romlott. Ez egy ésszerű kompromisszum lehet egy csak böngészőben működő widget esetén, de nem automatikusan a legjobb eredmény az elsődleges oldal tartalmaként.
1. lépés: Reprodukáld az eltérést és találd meg a legkisebb hibás komponenst
Kezdj egy kemény újratöltéssel fejlesztői módban, és olvasd el a teljes hibaüzenetet, beleértve a komponens stack-et is. A React 19 dokumentált hidratálási hibája több gyakori okot sorol fel: szerver/kliens elágazások, mint a typeof window !== 'undefined', változó értékek, mint a Date.now() vagy Math.random(), helyfüggő dátumformázás, külső adatok, amelyek pillanatkép nélkül változtak, érvénytelen HTML beágyazás, és böngészőbővítmények, amelyek módosítják a DOM-ot. Lásd a React 418-as hibát.
A Next.js hasonló listát ad a hivatalos hidratálási hibakalauzában, hozzáadva a csak böngészőben elérhető API-kat, mint a window és a localStorage, a CSS-in-JS konfigurációt, és az Edge/CDN réteg által módosított HTML-t.
AI-generált illusztráció: Szűkítsd a hibát arra a kifejezésre, amely eltérő értéket produkálhat a szerveren és a böngészőben, például dátum, véletlenszám, helyi beállítás vagy böngészőből származó érték. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
Egy gyakorlati izolálási módszer, hogy ideiglenesen determinisztikus szöveggel helyettesíted a gyanús dinamikus szakaszokat. Ha a hiba eltűnik, állítsd vissza ezeket a szakaszokat egyesével. Ez általában gyorsabb, mint a globális renderelési beállítások megváltoztatása, mielőtt tudnád, melyik komponens a felelős.
Minőségi jelzés
Amikor meg tudod nevezni mind a hibás komponenst, mind azt az értéket vagy struktúrát, amely eltér, akkor léphetsz tovább. Az "Ez valahol a dashboardon történik" még túl általános. A "A StatusCard időbélyege függetlenül jön létre a szerveren és a kliensen" már cselekvésre ösztönző.
2. lépés: Távolítsd el a nem determinisztikus értékeket az első renderelésből
A determinisztikus renderelés azt jelenti, hogy ugyanazok a bemenetek ugyanazt a kezdeti UI-t eredményezik. Azok az értékek, amelyek függetlenül változnak a szerveroldali és a böngészőoldali renderelés között, gyakori eltérési források.
Vizsgáljuk meg ezt a problémás mintát:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
A szerver és a böngésző ezt a kódot különböző pillanatokban és különböző helyi beállításokban vagy időzónákban futtathatja. Egy jobb megoldás attól függ, mit kell kommunikálnia az oldalnak.
Ha az időbélyeg szerveradatot reprezentál, számítsd ki vagy töltsd le egyszer a szerveren, és add át ugyanazt a sorozatba rendezett értéket a kliensnek:
Ha az érték valóban a felhasználó böngészőjétől függ, először egy stabil helykitöltőt jeleníts meg, és frissítsd a hidratálás után.
AI-generált illusztráció: Egy stabil kezdeti érték tiszta hidratálást tesz lehetővé, majd a böngészőspecifikus tartalom alkalmazható a komponens felépítése (mount) után. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
Ez azért működik, mert a szerver és az első kliensoldali renderelés is ugyanazt a helykitöltőt állítja elő. A React useEffect dokumentációja írja le ezt a kétfázisú mintát azokban a ritka esetekben, amikor a kliensoldali tartalomnak el kell térnie a szerveroldali tartalomtól.
Mikor változtass megközelítést
Ha a csak böngészőben elérhető érték a komponens teljes célja – például egy localStorage-ból visszaállított szerkesztő vagy egy widget, amely nem tud értelmesen renderelni a szerveren –, akkor a helykitöltő és hatás minta kényszerítése az egész komponensre felesleges bonyodalmat okozhat. Ebben az esetben használj egy szándékos, csak böngészőre korlátozott határt ahelyett, hogy úgy tennél, mintha a komponens szerveroldalon is renderelhető lenne.
3. lépés: Ne olvass csak böngészőben elérhető API-kat az első szerverkompatibilis renderelés során
Egy gyakori tévhit a Next.js-ben, hogy a 'use client' hozzáadása garantálja, hogy a komponens csak a böngészőben renderelődik. Ez nem igaz. A Next.js azt magyarázza, hogy a Client Components (kliens komponensek) a határok az állapot, hatások, eseménykezelők és böngésző API-k számára, de a Client Components részt vehetnek az előrenderelésben (prerendering). Lásd a jelenlegi use client dokumentációt.
A szerveren a localStorage nem létezik. Még egy olyan elágazás is, mint a typeof window !== 'undefined', eltérő markupot hozhat létre az első böngészőoldali rendereléskor, amit a React és a Next.js is hidratálási eltérés okaként dokumentál.
Kis eltérések esetén helyezd át a böngészőolvasást egy Effectbe. Egy olyan komponens esetén, amelynek valóban csak böngészőben kellene futnia a Next.js-ben, dinamikusan betöltheted azt az SSR letiltásával:
AI-generált illusztráció: Használj csak kliensre korlátozott határt azokhoz a komponensekhez, amelyek alapvetően böngésző API-kra támaszkodnak, ahelyett, hogy hagynád, hogy a szerver és a böngésző eltérő fákat rendereljen. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
A Next.js dokumentálja az ssr: false opciót a Client Components esetén a lazy loading (lusta betöltés) útmutatójában. Ugyanez az útmutató kimondja, hogy az ssr: false nem támogatott, ha ezt az opciót közvetlenül egy Server Componentben (szerver komponensben) próbálod használni; helyezd át a dinamikus importot egy Client Componentbe.
React 19.3: egy elsődleges, csak böngésző opció
A React 19.3 bevezette a browser API-t. Egy komponens meghívhatja a use(browser()) függvényt egy Suspense határon belül, hogy kizárja a komponenst a szerveroldali renderelésből. A szerver a Suspense fallback-ot rendereli, míg a komponens normálisan renderelődik a böngészőben. Lásd a React browser API referenciáját.
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>
);
}
Egy React Server Components alkalmazásban a React azt mondja, hogy a use(browser()) hívást egy Client Componentből kell meghívni. Ellenőrizd továbbá, hogy a keretrendszered és a telepített React verzió elérhetővé teszi-e ezt az API-t, mielőtt átállnál rá.
4. lépés: Tedd a szerveradatokat és az első kliensadatokat ugyanazzá a pillanatképpé
Egy pillanatkép (snapshot) az a pontos adatállapot, amelyet a kezdeti HTML előállításához használnak. A hidratálás törékennyé válik, ha a szerver egy adatverziót renderel, és a kliens azonnal egy újabb vagy másképp rendezett verziót olvas a hidratálás befejezése előtt.
AI-generált illusztráció: Az első kliensoldali renderelésnek ugyanazt a kezdeti adatpillanatképet kell fogyasztania, amely a szerver HTML-t előállította; a későbbi frissítések a hidratálás után történhetnek. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
Például, tegyük fel, hogy a szerver 99 dolláros árat renderel, de a kliens azonnal lekérdezi ugyanazt a terméket, és 109 dollárt kap az első renderelés előtt. A probléma nem az, hogy az adat megváltozott; az adatváltozás normális. A probléma az, hogy a két környezet különböző kezdeti bemeneteket használt.
Egy erős minta:
Töltsd le a kezdeti adatokat a szerveren.
Rendereld a HTML-t ebből az adatból.
Add át vagy sorozatba rendezd ugyanazt a kezdeti adatot a kliens komponensbe.
A hidratálás után engedélyezd a kliensnek az újrafüggő validálást és frissítést, ha újabb adatok léteznek.
A helyes megvalósítás a keretrendszered adatlekérési modelljétől függ, de a minőségi kritérium ugyanaz marad: a szerver HTML-nek és az első kliensoldali fának ugyanazon logikai állapoton kell alapulnia.
Mikor változtass megközelítést
Ha a tartalom eredendően valós idejű, és egy elavult szerverpillanatkép félrevezetné a felhasználókat – például egy élő kereskedési widget vagy gyorsan változó műveleti konzol –, fontold meg egy stabil váz renderelését a szerveren, és az élő szekció betöltését a kliensen. Ez feláldoz némi szerveroldali tartalmat abban a régióban, de lehet, hogy őszintébb, mint olyan adatokhoz hidratálni, amelyekről garantált, hogy megváltoznak.
5. lépés: Javítsd ki az érvénytelen HTML-t, mielőtt a Reactet okolnád
A böngészőknek joguk van kijavítani a hibásan formázott vagy érvénytelenül beágyazott HTML-t. Ez a javítás olyan DOM-struktúrát eredményezhet, amely eltér a React által várt struktúrától, még akkor is, ha a JSX vizuálisan hihetőnek tűnt.
AI-generált illusztráció: Ellenőrizd a szemantikus HTML beágyazást, amikor a komponensfa determinisztikusnak tűnik, de a böngésző mégis eltérő DOM-ot épít. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
A Next.js kifejezetten felsorol példákat, mint például egy <div> egy <p>-n belül, egy lista egy bekezdésben, egymásba ágyazott horgonyok (<a>), és egymásba ágyazott gombok mint hidratálási problémák okai.
Például kerüld el ezt:
<p>
Intro text
<div>Details</div>
</p>
Használj inkább egy érvényes struktúrát:
<div>
<p>Intro text</p>
<div>Details</div>
</div>
Ha egy komponenskönyvtár generálja a markupot, vizsgáld meg a végső DOM-ot ahelyett, hogy feltételeznéd, hogy a wrapper elemek érvényesek. Egy lint szabály vagy HTML validátor segíthet, de a böngésző tényleges DOM-ja az, amit a React hidratál.
6. lépés: Zárd ki a komponensen kívüli kódot
Ha a renderelési logikád determinisztikus és a HTML-ed érvényes, ellenőrizd, hogy valami módosítja-e a szerver HTML-t, mielőtt a React hidratálná azt.
A hivatalos Next.js dokumentáció több lehetőséget nevesít:
Egy böngészőbővítmény módosítja az oldalt a React betöltése előtt.
Egy CSS-in-JS könyvtár helytelenül van konfigurálva a szerveroldali rendereléshez.
Egy Edge vagy CDN funkció átírja vagy minifikálja a HTML választ.
iOS-en az automatikus telefonszám, e-mail cím, dátum vagy cím felismerés bizonyos esetekben szöveget linkekké alakíthat.
Használj kontrollált összehasonlításokat. Tesztelj egy privát böngészőablakban letiltott bővítményekkel. Ha a hiba csak egy CDN mögött jelentkezik, hasonlítsd össze az origin (eredeti) válaszval. Ha egy stílus könyvtár bevezetése után kezdődött, kövesd az adott könyvtár hivatalos SSR konfigurációját, ahelyett, hogy általános hidratálási workaroundot alkalmaznál.
Minőségi jelzés
Akkor izoláltad ezt a problémaosztályt, amikor ugyanaz az alkalmazás build helyesen hidratálódik egy kontrollált környezetben, de elbukik, miután egy specifikus böngészőbővítmény, proxy, CDN transzformáció vagy integráció megváltoztatja a HTML-t.
7. lépés: Használd a suppressHydrationWarning opciót csak valóban elkerülhetetlen, helyi eltérés esetén
A React biztosítja a suppressHydrationWarning={true} opciót ritka esetekre, amikor egyetlen elem szövege vagy attribútumai nem tudnak ésszerűen egyezni, például bizonyos időbélyegek esetén.
Ez nem egy általános javítási mechanizmus. A React common DOM props dokumentációja azt mondja, hogy az opció csak egy szint mélyen működik, és egy menekülési útvonalnak (escape hatch) szánják. A Next.js hidratálási útmutatója is figyelmeztet, hogy a React nem fogja megpróbálni kijavítani az eltérő szövegtartalmat, ha ezt az opciót használják.
Csak akkor használd, ha az alábbiak mindegyike igaz:
Az eltérés várt és lokalizált.
Az eltérés nem jelent helytelen alkalmazásállapotot.
A környező struktúra stabil.
Tudatosan elfogadtad, hogy a kezdeti szerverérték és böngészőérték eltér.
Ha a prop hozzáadása tucatnyi figyelmeztetést tüntet el, az egy ok a további vizsgálatra, nem pedig arra, hogy az alapvető probléma megoldódott.
8. lépés: Ellenőrizd a javítást fejlesztői és éles környezetben
AI-generált illusztráció: A kód megváltoztatása után ellenőrizd a tiszta újratöltést, a helyes interaktivitást és egy éles buildet, ahelyett, hogy csak a fejlesztői átfedésre támaszkodnál. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
A fejlesztői viselkedés eltérhet az optimalizált éles buildtől. Miután a hiba eltűnt helyileg, végezz egy éles-stílusú ellenőrzést a keretrendszeredhez. Egy tipikus Next.js projekt esetén ez gyakran azt jelenti, hogy buildelsz és elindítod az alkalmazást a szokásos csomagkezelő parancsaiddal, majd friss navigációkat és újratöltéseket végzel.
Használd ezt az ellenőrző listát:
Ellenőrzés
Jó jel
Ha elbukik
Friss újratöltés
Nincs hidratálási hiba a konzolban
Ellenőrizd újra a legkorábbi eltérő komponenst
Kezdeti vizuális állapot
Nincs nem kívánt villanás vagy csere
Tedd determinisztikussá a kezdeti állapotot
Interakciók
A gombok, űrlapok, menük és állapotok normálisan működnek
Erősítsd meg, hogy a komponens még mindig hidratálódik és az eseménykezelők csatolódnak
Éles build
Ugyanaz a helyes eredmény, mint fejlesztésben
Vizsgáld meg a csak éles környezetben fellépő adatokat, CDN-t, CSS-t vagy optimalizálási viselkedést
Letiltott bővítmények
Az eredmény változatlan
Azonosítsd a DOM-ot módosító bővítmény viselkedését
Ha közvetlenül te birtoklod a React SSR belépési pontját egy keretrendszer használata helyett, a hydrateRoot is támogat hiba visszahívásokat, mint például az onRecoverableError, ami segíthet az éles naplózásban. A keretrendszer felhasználóinak általában nem kellene lecserélniük a keretrendszer hidratálási belépési pontját csak egyedi kezelés hozzáadása érdekében.
Mikor próbálj ki egy másik renderelési stratégiát
AI-generált illusztráció: Válts stratégiát, amikor egy komponens alapvetően nem tud értelmes szerver HTML-t előállítani, de tartsd a csak kliens határt a lehető legkisebbre. Ez nem egy valódi böngésző, React vagy Next.js képernyőkép; használd a cikkben szereplő ellenőrzött kódokat és dokumentációs linkeket mint megbízható forrást.
Néha a legjobb javítás nem az, hogy egy komponenst SSR-be kényszerítesz. Fontolj meg egy másik renderelési stratégiát, amikor:
A komponens a window, canvas, WebGL, böngészőmérések vagy más csak böngésző API köré épül.
Egy harmadik féltől származó widget hivatalosan nem támogatja az SSR-t.
A komponens értelmes tartalma teljesen eszköz-helyi állapottól, mint a localStorage, függ.
A valós idejű adatok olyan gyorsan változnak, hogy egy szerverpillanatképhez igazodnak kevés értékkel bír.
Ezekben az esetekben egy célzott, csak kliens határ tisztább lehet. A kulcsszó a célzott. Az SSR letiltása egy egész oldalra egyetlen diagram vagy szerkesztő miatt feleslegesen áldozhat fel hasznos szerveroldali tartalmat, betöltési viselkedést és egyéb előnyöket.
Gyakori javítások, amelyek sikeresnek tűnnek, de nem azok
Rövidítés
Miért hiányos
Jobb kritérium
Add hozzá a 'use client' mindenhová
A Client Components még mindig előrenderelhetők a Next.js-ben
Helyezd át a csak böngésző logikát a hidratálás utánra, vagy izoláld szándékosan
Csomagold be a renderelési logikát typeof window !== 'undefined' köré
Az elágazás önmagában is eltérő első render markupot hozhat létre
Tartsd az első renderelést azonosnak
Használd széles körben a suppressHydrationWarning-ot
Ez elrejt egy figyelmeztetést ahelyett, hogy egyeztetné az alkalmazás állapotát
Használd csak egy várt, helyi, elkerülhetetlen eltérés esetén
Tilt le az SSR-t az egész oldalra
Ez eltüntetheti a tünetet azáltal, hogy túl sok UI-ra kikapcsolja a hidratálást
Használd a legkisebb gyakorlati csak kliens határt
Tesztelj csak kliensoldali navigációt
Egy eltérés csak közvetlen kérésnél vagy kemény újratöltésnél jelenhet meg
Tesztelj friss szerveroldali oldalbetöltéseket
Ezen javítások korlátai
Egy hidratálási hiba azt mondja el, hogy a szerver és a kliens renderelése eltért; nem bizonyítja, hogy miért. Ugyanaz a tünet származhat alkalmazás logikából, böngésző módosításból, egy könyvtárból, egy CDN-ből, hibás HTML-ből vagy változó adatokból. Nincs egyetlen kódrészlet, amely biztonságosan javítaná az összes ilyen esetet.
Továbbá, a hidratálási figyelmeztetések eltávolítása nem garantálja a helyességet máshol. Egy csak kliens komponensnek még mindig lehetnek adatversenyi (data race) problémái. Egy determinisztikus első renderelés még mindig mutathat elavult adatokat a hidratálás után. Egy érvényes DOM még mindig tartalmazhat hozzáférhetőségi problémákat. Kezeld a hidratálást egy minőségi kapuként, nem pedig az egyetlenként.
A React 19.3 új browser API-ja sem azt jelenti, hogy minden keretrendszernek azonnal le kellene cserélnie a bevett, csak böngésző mintáját. A keretrendszer integrációja és a telepített verziók számítanak. Ha a projekted egy régebbi React vagy Next.js kiadáson van, kövesd az adott kiadás dokumentációját, ahelyett, hogy vakon másolnál egy újabb API-t.
Megbízható döntési sorrend
Találd meg a legkisebb komponenst, amely eltér.
Ellenőrizd a változó értékeket, mint dátumok, véletlenszámok, helyi formázás és kétszer lekért adatok.
Távolítsd el a csak böngésző API-kat az első szerverkompatibilis renderelésből.
Biztosítsd, hogy a szerver és az első kliens renderelés ugyanazt az adatpillanatképet használja.
Validáld a HTML struktúrát.
Zárd ki a bővítményeket, CSS-in-JS SSR konfigurációt és CDN/Edge átírást.
Használj Effectet, célzott csak kliens renderelést vagy React 19.3 use(browser()) függvényt csak akkor, ha a tartalom valóban a böngészőtől függ.
Tartsd fenn a suppressHydrationWarning-ot kis, szándékos eltérésekhez.
Ellenőrizd egy friss újratöltéssel és egy éles builddel.
A tartós javítás nem az, hogy "kapcsold ki a React panaszkodását". Az, hogy tegyél explicité a kezdeti renderelési szerződést: a szervernek és a böngészőnek meg kell egyeznie az első UI-ban, vagy a csak böngésző szekciót szándékosan izolálni kell, hogy a React ne legyen arra kényszerítve, hogy olyan markupot hidratáljon, amely soha nem egyezhetne meg.