Domov
» Osnovno znanje
»
Kako odpraviti napako "Hydration failed because the initial UI does not match"
Kako odpraviti napako "Hydration failed because the initial UI does not match"
Želeni rezultat je preprost za opis: HTML, ustvarjen na strežniku, se mora ujemati s tem, kar React ustvari ob prvem izrisu v brskalniku. Ko je to res, lahko React priključi obravnavanje dogodkov in naredi stran interaktivno, ne da bi sprožil neskladje pri hidrataciji, zamenjal poddrevo ali prikazal nepričakovan vizualni skok.
Hidratacija je postopek, pri katerem React prevzame HTML, ki je bil že izrisan na strežniku, in mu v brskalniku doda obnašanje React. Trenutna dokumentacija za hydrateRoot navaja, da se pričakuje, da bo vsebina, izrisana na odjemalcu, identična vsebini, izrisani na strežniku, in da je treba neskladja obravnavati kot napake.
>Točno besedilo napake se je skozi izdaje React in okvirjev (framework) spremenilo. Morda boste videli starejše sporočilo, kot je "Hydration failed because the initial UI does not match what was rendered on the server", ali novejšo razlago, da drevo, izrisano na strežniku, ne ustreza odjemalcu. Načelo razhroščevanja je enako.
Kontekst različice je pomemben. Po stanju 11. septembra 2026 uradno spletno mesto React navaja React 19.3 kot najnovejšo različico React, trenutna dokumentacija Next.js pa kot najnovejšo izdajo Next.js navaja Next.js 16.3.4. Preverite stran z različicami React in trenutno dokumentacijo Next.js, če to berete kasneje, saj se lahko razpoložljivi API-ji in sporočila o napakah spremenijo.
Ilustracija, ustvarjena z umetno inteligenco: Začnite tako, da poiščete prvo komponento, navedeno v napaki pri hidrataciji, in potrdite, da se težava pojavi ob svežem naložitvi strani. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Kaj šteje za uspešen popravek?
Uspeha ne ocenjujte samo po tem, ali rdeč razvojni prekrivni sloj izgine. Dober popravek mora izpolnjevati več preverjanj:
Opozorilo ali napaka pri hidrataciji se ob čistem ponovnem nalaganju ne pojavi več.
Začetni uporabniški vmesnik, izrisan na strežniku, in prvi izris React v brskalniku predstavljata isto vsebino in strukturo.
Zadevna komponenta ostane interaktivna po hidrataciji.
Ni očitnega utripa iz ene vrednosti v drugo, razen če je ta sprememba namenoma zasnovana.
Težava ostane odpravljena v produkcijski gradnji, ne le v razvojnem strežniku.
Popravili ste vzrok, namesto da bi skrili dejansko neskladje z možnostjo za utišanje opozoril.
Če opozorilo izgine, vendar stran zdaj pomembno vsebino izriše šele po nalaganju JavaScripta, je morda napaka izginila, uporabniška izkušnja pa se je poslabšala. To je lahko razumen kompromis za gradnik, ki deluje samo v brskalniku, ni pa samodejno najboljša rešitev za primarno vsebino strani.
Korak 1: Ponovno ustvarite neskladje in poiščite najmanjšo okvarjeno komponento
Začnite s trdim ponovnim nalaganjem v razvojnem okolju in preberite celotno napako, vključno s skladom komponent. Dokumentirana napaka pri hidrataciji v React 19 našteva več pogostih vzrokov: veje strežnik/odjemalec, kot je typeof window !== 'undefined', spreminjajoče se vrednosti, kot sta Date.now() ali Math.random(), oblikovanje datumov, odvisno od lokalne nastavitve, zunanji podatki, ki so se spremenili brez posnetka, neveljavno gnezdenje HTML in razširitve brskalnika, ki spreminjajo DOM. Glejte napako React 418.
Next.js podaja podoben seznam v svojem uradnem vodniku za napake pri hidrataciji, dodajajoč API-je, ki so na voljo samo v brskalniku, kot sta window in localStorage, konfiguracijo CSS-in-JS ter HTML, ki ga je spremenila plast Edge/CDN.
Ilustracija, ustvarjena z umetno inteligenco: Omejite napako na izraz, ki lahko ustvari različne vrednosti na strežniku in v brskalniku, kot so datum, naključno število, lokalna nastavitev ali vrednost, pridobljena iz brskalnika. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Praktična metoda izolacije je, da začasno nadomestite sumljive dinamične razdelke z determinističnim besedilom. Če napaka izgine, te razdelke obnovite enega za drugim. To je običajno hitrejše kot spreminjanje globalnih nastavitev izrisa, preden veste, katera komponenta je odgovorna.
Signal kakovosti
Pripravljeni ste za nadaljevanje, ko lahko poimenujete tako okvarjeno komponento kot vrednost ali strukturo, ki se razlikuje. "To se zgodi nekje v nadzorni plošči" je še vedno preširoko. "Časovni žig v StatusCard se neodvisno ustvari na strežniku in odjemalcu" je ukrepljivo.
Korak 2: Odstranite nedeterministične vrednosti iz začetnega izrisa
Deterministično izrisovanje pomeni, da isti vhodi ustvarijo enak začetni uporabniški vmesnik. Vrednosti, ki se neodvisno spreminjajo med izrisom na strežniku in izrisom v brskalniku, so pogosti viri neskladij.
Premislite ta problematičen vzorec:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
Strežnik in brskalnik lahko ta koda izvedeta v različnih trenutkih ter v različnih lokalnih nastavitvah ali časovnih conah. Boljša rešitev je odvisna od tega, kaj stran želi sporočiti.
Če časovni žig predstavlja podatke s strežnika, jih izračunajte ali pridobite enkrat na strežniku in posredujte isto serializirano vrednost odjemalcu:
Če vrednost resnično temelji na brskalniku uporabnika, najprej izrišite stabilen rezervirani prostor in ga posodobite po hidrataciji.
Ilustracija, ustvarjena z umetno inteligenco: Stabilna začetna vrednost se lahko čisto hidrira, nato pa se lahko vsebina, specifična za brskalnik, uporabi po tem, ko se komponenta namesti. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
To deluje, ker strežnik in prvi izris odjemalca oba ustvarita enak rezervirani prostor. Dokumentacija za useEffect opisuje ta dvostopenjski vzorec za redke primere, ko se mora vsebina na odjemalcu razlikovati od vsebine na strežniku.
Kdaj spremeniti pristop
Če je vrednost, ki je na voljo samo v brskalniku, celoten namen komponente – na primer urejevalnik, obnovljen iz localStorage, ali gradnik, ki se ne more smiselno izrisati na strežniku – lahko vsiljevanje vzorca rezervirani prostor-učinek po celotni komponenti doda nepotrebno zapletenost. V tem primeru uporabite namerno mejo samo za brskalnik, namesto da bi se pretvarjali, da je komponenta izrisljiva na strežniku.
Korak 3: Ne berite API-jev, ki so na voljo samo v brskalniku, med prvim izrisom, združljivim s strežnikom
>Pogosta zmota v Next.js je, da dodajanje 'use client' zagotavlja, da se komponenta izriše samo v brskalniku. Ne zagotavlja. Next.js pojasnjuje, da so komponente odjemalca meja za stanje, učinke, obravnavanje dogodkov in API-je brskalnika, vendar lahko komponente odjemalca še vedno sodelujejo pri predhodnem izrisu. Glejte trenutno dokumentacijo za use client.
Na strežniku localStorage ne obstaja. Tudi veja, kot je typeof window !== 'undefined', lahko ustvari različno oznako ob prvem izrisu v brskalniku, kar React in Next.js oba dokumentirata kot vzrok za neskladje pri hidrataciji.
Za majhne razlike premaknite branje iz brskalnika v Učinek. Za komponento, ki bi morala biti v Next.js resnično samo za brskalnik, jo lahko dinamično naložite z onemogočenim SSR:
Ilustracija, ustvarjena z umetno inteligenco: Uporabite mejo samo za odjemalca za komponente, ki temeljno temeljijo na API-jih brskalnika, namesto da bi pustili, da strežnik in brskalnik izrišeta različni drevesi. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Next.js dokumentira ssr: false za komponente odjemalca v svojem vodniku za leno nalaganje. Isti vodnik navaja, da ssr: false ni podprt, ko poskušate to možnost uporabiti neposredno v komponenti strežnika; premaknite dinamični uvoz v komponento odjemalca.
React 19.3: prvorazredna možnost samo za brskalnik
React 19.3 je uvedel API browser. Komponenta lahko pokliče use(browser()) znotraj meje Suspense, da to komponento izključi iz izrisovanja na strežniku. Strežnik izriše rezervirani prostor Suspense, medtem ko se komponenta normalno izriše v brskalniku. Glejte referenco za API browser v React.
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 aplikaciji React Server Components React navaja, da je treba use(browser()) klicati iz komponente odjemalca. Prav tako preverite, ali vaš okvir in nameščena različica React izpostavljata ta API, preden ga začnete uporabljati.
Korak 4: Uskladite podatke s strežnika in prve podatke odjemalca v isti posnetek
Posnetek je točno stanje podatkov, uporabljeno za ustvarjanje začetnega HTML. Hidratacija postane krhka, če strežnik izriše eno različico podatkov, odjemalec pa takoj prebere novejšo ali drugače razvrščeno različico, preden se hidratacija zaključi.
Ilustracija, ustvarjena z umetno inteligenco: Prvi izris odjemalca bi moral porabiti isti začetni posnetek podatkov, ki je ustvaril HTML na strežniku; kasnejše posodobitve se lahko zgodijo po hidrataciji. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Na primer, predpostavimo, da strežnik izriše ceno 99 $, odjemalec pa takoj pridobi isti izdelek in dobi 109 $ pred svojim prvim izrisom. Težava ni v tem, da so se podatki spremenili; spreminjanje podatkov je normalno. Težava je v tem, da sta dva okolja uporabila različne začetne vhode.
Močan vzorec je:
Pridobite začetne podatke na strežniku.
Izrišite HTML iz teh podatkov.
Posredujte ali serializirajte iste začetne podatke v komponento odjemalca.
Po hidrataciji dovolite odjemalcu, da ponovno preveri in posodobi, če obstajajo novejši podatki.
Pravilna izvedba je odvisna od modela pridobivanja podatkov vašega okvirja, vendar merilo kakovosti ostaja enako: HTML na strežniku in prvo drevo odjemalca bi morala temeljiti na istem logičnem stanju.
Kdaj spremeniti pristop
Če je vsebina inherentno v realnem času in bi zastarel posnetek s strežnika zavajal uporabnike – na primer gradnik za trgovanje v živo ali konzola za operacije, ki se hitro spreminja – razmislite o izrisovanju stabilne lupine na strežniku in nalaganju razdelka v živo na odjemalcu. To pomeni odpoved delu vsebine, izrisane na strežniku za to območje, vendar je morda bolj pošteno kot hidratacija glede na podatke, za katere je zagotovljeno, da se bodo spremenili.
Korak 5: Popravite neveljaven HTML, preden krivite React
Brskalnikom je dovoljeno popraviti nepravilno oblikovan ali neveljavno gnezden HTML. To popravilo lahko ustvari strukturo DOM, ki se razlikuje od strukture, ki jo pričakuje React, tudi če je JSX vizualno deloval verjetno.
Ilustracija, ustvarjena z umetno inteligenco: Preverite semantično gnezdenje HTML, ko se drevo komponent zdi deterministično, vendar brskalnik še vedno zgradi drugačen DOM. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Next.js izrecno našteva primere, kot so <div> znotraj <p>, seznam znotraj odstavka, gnezdeni sidri in gnezdeni gumbi, kot vzroke za težave s hidratacijo.
Na primer, izogibajte se:
<p>
Intro text
<div>Details</div>
</p>
Namesto tega uporabite veljavno strukturo:
<div>
<p>Intro text</p>
<div>Details</div>
</div>
Če knjižnica komponent ustvari oznako, preglejte končni DOM, namesto da bi predpostavljali, da so ovojni elementi veljavni. Pravilo lint ali validator HTML lahko pomaga, vendar je dejanski DOM brskalnika tisti, ki ga React hidrira.
Korak 6: Izključite kodo zunaj komponente
Če je vaša logika izrisa deterministična in je vaš HTML veljaven, preverite, ali nekaj spreminja HTML s strežnika, preden ga React hidrira.
Uradna dokumentacija Next.js našteva več možnosti:
Razširitev brskalnika spremeni stran, preden se naloži React.
Knjižnica CSS-in-JS je napačno konfigurirana za izrisovanje na strežniku.
Funkcija Edge ali CDN prepiše ali minimizira odgovor HTML.
Na iOS lahko samodejno zaznavanje telefonskih številk, e-poštnih naslovov, datumov ali naslovov v nekaterih primerih spremeni besedilo v povezave.
Uporabite nadzorovane primerjave. Testirajte v zasebnem oknu brskalnika z onemogočenimi razširitvami. Če se napaka pojavi samo za CDN, jo primerjajte z odgovorom izvora. Če se je začela po uvedbi knjižnice za oblikovanje, sledite uradni konfiguraciji SSR te knjižnice, namesto da bi uporabljali splošni zaobid za hidratacijo.
Signal kakovosti
To vrsto težave ste izolirali, ko se ista gradnja aplikacije pravilno hidrira v enem nadzorovanem okolju, vendar odpove, ko določena razširitev brskalnika, proxy, transformacija CDN ali integracija spremeni HTML.
Korak 7: Uporabite suppressHydrationWarning samo za res neizogibno lokalno razliko
React zagotavlja suppressHydrationWarning={true} za redke primere, ko besedilo ali atributi enega samega elementa ne morejo razumno ustrezati, kot so določeni časovni žigi.
To ni splošen mehanizem za popravilo. Dokumentacija za skupne lastnosti DOM v React navaja, da možnost deluje samo eno raven globoko in je namenjena kot izhod v sili. Vodnik za hidratacijo Next.js tudi opozarja, da React ne bo poskušal popraviti neskladnega besedila, ko je ta možnost uporabljena.
Uporabite jo samo, ko veljajo vse naslednje trditve:
Razlika je pričakovana in lokalizirana.
Neskladje ne predstavlja napačnega stanja aplikacije.
Okolna struktura je stabilna.
Zavedajoč ste se sprejeli, da se začetna vrednost na strežniku in vrednost v brskalniku razlikujeta.
Če dodajanje lastnosti povzroči, da izginejo desetine opozoril, je to razlog za nadaljnje raziskovanje, ne znak, da je osnovna težava rešena.
Korak 8: Preverite popravek v razvojnem in produkcijskem okolju
Ilustracija, ustvarjena z umetno inteligenco: Po spremembi kode preverite čisto ponovno nalaganje, pravilno interaktivnost in produkcijsko gradnjo, namesto da bi se zanašali samo na razvojni prekrivni sloj. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Vedenje v razvojnem okolju se lahko razlikuje od optimizirane produkcijske gradnje. Ko napaka lokalno izgine, izvedite preverjanje v slogu produkcijskega okolja za svoj okvir. Za tipičen projekt Next.js to pogosto pomeni gradnjo in zagon aplikacije z običajnimi ukazi upravitelja paketov, nato pa izvedbo svežih navigacij in ponovnih naložitev.
Uporabite ta kontrolni seznam za preverjanje:
Preverjanje
Dobri znak
Če ne uspe
Sveža ponovna nalaganje
Brez napake pri hidrataciji v konzoli
Ponovno preverite najzgodnejšo različno komponento
Začetni vizualni stanje
Brez nepričakovanega utripanja ali zamenjave
Naredite začetno stanje deterministično
Interakcije
Gumbi, obrazci, meniji in stanje delujejo normalno
Potrdite, da se komponenta še vedno hidrira in se obravnavanje dogodkov priključi
Produkcijska gradnja
Isti pravilen rezultat kot v razvojnem okolju
Raziščite podatke, CDN, CSS ali obnašanje optimizacije, ki so samo v produkcijskem okolju
Razširitve onemogočene
Rezultat je nespremenjen
Identificirajte obnašanje razširitve, ki spreminja DOM
Če neposredno upravljate vstopno točko SSR React namesto uporabe okvirja, hydrateRoot podpira tudi povratne klice za napake, kot je onRecoverableError, kar lahko pomaga pri beleženju v produkcijskem okolju. Uporabniki okvirjev na splošno ne bi smeli zamenjati vstopne točke hidratacije okvirja samo za dodajanje lastne obravnave.
Kdaj poskusiti z drugačno strategijo izrisovanja
Ilustracija, ustvarjena z umetno inteligenco: Spremenite strategijo, ko komponenta temeljno ne more ustvariti smiselne HTML na strežniku, vendar ohranite mejo samo za odjemalca čim manjšo, kot je praktično. To ni dejanski posnetek zaslona brskalnika, React ali Next.js; kot vir resnice uporabite preverjene povezave do kode in dokumentacije v članku.
Včasih najboljši popravek ni vsiljevanje komponente v SSR. Razmislite o drugačni strategiji izrisovanja, ko:
Je komponenta zgrajena okoli window, platna, WebGL, meritev brskalnika ali drugega API-ja, ki je na voljo samo v brskalniku.
Gradnik tretje osebe uradno ne podpira SSR.
Pomembna vsebina komponente popolnoma temelji na stanju, lokalnem za napravo, kot je localStorage.
Se podatki v realnem času spreminjajo tako hitro, da ujemanje s posnetkom s strežnika nima velike vrednosti.
V teh primerih je lahko ciljna meja samo za odjemalca čistejša. Ključna beseda je ciljna. Onemogočanje SSR za celotno stran zaradi enega grafa ali urejevalnika lahko nepotrebno žrtvuje uporabno vsebino, izrisano na strežniku, obnašanje pri nalaganju in druge prednosti.
Pogosti popravki, ki videti uspešni, a niso
Bližnjica
Zakaj je nepopolna
Boljše merilo
Dodajte 'use client' povsod
Komponente odjemalca so lahko v Next.js še vedno predhodno izrisane
Premaknite logiko, ki je na voljo samo v brskalniku, za hidratacijo ali jo namerno izolirajte
Ovijte logiko izrisa v typeof window !== 'undefined'
Sama veja lahko ustvari različno oznako ob prvem izrisu
Ohranite prvi izris identičen
Uporabite suppressHydrationWarning na široko
Skrije opozorilo, namesto da bi uskladil stanje aplikacije
Uporabite samo za pričakovano, lokalno, neizogibno neskladje
Onemogočite SSR za celotno stran
Lahko odstrani simptom z odstranitvijo hidratacije za preveč UI
Uporabite najmanjšo praktično mejo samo za odjemalca
Testirajte samo navigacijo na strani odjemalca
Neskladje se lahko pojavi samo ob neposredni zahtevi ali trdem ponovnem nalaganju
Testirajte sveža nalaganja strani, izrisane na strežniku
Omejitve teh popravkov
Napaka pri hidrataciji vam pove, da sta se izrisovanje na strežniku in odjemalcu razšla; ne dokazuje zakaj. Isti simptom lahko izvira iz logike aplikacije, mutacije brskalnika, knjižnice, CDN, nepravilno oblikovanega HTML ali spreminjajočih se podatkov. Ne obstaja en sam odsek kode, ki bi varno popravil vse te primere.
Poleg tega odstranitev opozoril pri hidrataciji ne zagotavlja pravilnosti drugje. Komponenta samo za odjemalca lahko še vedno ima tekmovanja podatkov. Deterministični prvi izris lahko še vedno prikaže zastarele podatke po hidrataciji. Veljaven DOM lahko še vedno vsebuje težave z dostopnostjo. Obravnavajte hidratacijo kot ena vrata kakovosti, ne kot edina.
Novi API browser v React 19.3 tudi ne pomeni, da bi moral vsak okvir takoj zamenjati svojo vzpostavljeno vzorec samo za brskalnik. Pomembni so integracija okvirja in nameščene različice. Če je vaš projekt na starejši izdaji React ali Next.js, sledite dokumentaciji za to izdajo, namesto da bi slepo kopirali novejši API.
Zanesljiv vrstni red odločanja
Poiščite najmanjšo komponento, ki se ne ujema.
Preverite spreminjajoče se vrednosti, kot so datumi, naključna števila, oblikovanje lokalne nastavitve in dvakrat pridobljeni podatki.
Odstranite API-je, ki so na voljo samo v brskalniku, iz prvega izrisa, združljivega s strežnikom.
Zagotovite, da strežnik in prvi izris odjemalca uporabljata isti posnetek podatkov.
Preverite veljavnost strukture HTML.
Izključite razširitve, konfiguracijo SSR CSS-in-JS in prepisovanje CDN/Edge.
Uporabite Učinek, ciljno izrisovanje samo za odjemalca ali React 19.3 use(browser()) samo, ko vsebina resnično temelji na brskalniku.
Pridržite suppressHydrationWarning za majhna, namerna neskladja.
Preverite s svežim ponovnim nalaganjem in produkcijsko gradnjo.
Trajni popravek ni "narediti, da React neha opozarjati". Je pa narediti začetno pogodbo o izrisovanju eksplicitno: strežnik in brskalnik bi se morala strinjati o prvem uporabniškem vmesniku, ali pa bi moral biti razdelek samo za brskalnik namerno izoliran, da React ne bo prosil za hidratacijo oznake, ki se nikoli ne bi mogla ujemati.