Sākums
» Pamatzināšanas
»
Kā novērst kļūdu “Hydration failed because the initial UI does not match”
Kā novērst kļūdu “Hydration failed because the initial UI does not match”
Vēlamais rezultāts ir viegli aprakstāms: serverī ģenerētajam HTML ir jāsakrīt ar to, ko React ģenerē pirmajā pārlūka renderēšanā. Kad tas tā ir, React var pievienot notikumu apstrādātājus un padarīt lapu interaktīvu, nemetot hidratācijas neatbilstības kļūdu, neaizstājot apakškoku vai nerādot negaidītu vizuālu lēcienu.
Hidratācija ir process, kurā React pārņem HTML, kas jau ir renderēts serverī, un pārlūkā tam pievieno React uzvedību. React pašreizējā hydrateRoot dokumentācija nosaka, ka klienta renderētajam saturam ir jābūt identiskam servera renderētajam saturam un ka neatbilstības ir jāuztver kā kļūdas.
Precīzais kļūdas formulējums ir mainījies dažādās React un ietvarprogrammu versijās. Jūs varat redzēt vecāku ziņojumu, piemēram, "Hydration failed because the initial UI does not match what was rendered on the server", vai jaunāku ziņojumu, kas skaidro, ka servera renderētais koks nesakrita ar klienta koku. Atkļūdošanas princips paliek tas pats.
Versijas konteksts ir svarīgs. Līdz 2026. gada 11. septembrim oficiālā React vietne norāda React 19.3 kā jaunāko React versiju, savukārt pašreizējā Next.js dokumentācija norāda Next.js 16.3.4 kā jaunāko Next.js izlaidumu. Pārbaudiet React versiju lapu un pašreizējo Next.js dokumentāciju, ja lasāt šo vēlāk, jo pieejamās API un kļūdu ziņojumi var mainīties.
AI ģenerēta ilustrācija: Sāciet, atrodot pirmo komponenti, kas minēta hidratācijas kļūdā, un apstipriniet, ka problēma rodas, ielādējot jaunu lapu. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Kas tiek uzskatīts par veiksmīgu labojumu?
Nenovērtējiet panākumus tikai pēc tā, vai sarkanais izstrādes pārklājums pazūd. Labs labojumam jāatbilst vairākām pārbaudēm:
Hidratācijas brīdinājums vai kļūda vairs neparādās pēc tīras pārlādēšanas.
Sākotnējais servera renderētais UI un pārlūka pirmais React renderējums attēlo vienu un to pašu saturu un struktūru.
Skartā komponente paliek interaktīva pēc hidratācijas.
Nav acīmredzamas mirgošanas no vienas vērtības uz citu, ja vien šī maiņa nav apzināta un dizainēta.
Problēma paliek novērsta produkcijas būvē, ne tikai izstrādes serverī.
Jūs esat izlabojis cēloni, nevis paslēpis reālu neatbilstību, izmantojot brīdinājumu apspiešanas opciju.
Ja brīdinājums pazūd, bet lapa tagad renderē svarīgu saturu tikai pēc JavaScript ielādes, kļūda var būt izzudusi, bet lietotāja pieredze ir pasliktinājusies. Tas var būt saprātīgs kompromiss tikai pārlūkam paredzētam logrīkam, taču tas nav automātiski labākais rezultāts galvenajam lapas saturam.
1. darbība: Atkārtojiet neatbilstību un atrodiet mazāko kļūdaino komponenti
Sāciet ar piespiedu pārlādēšanu izstrādes vidē un izlasiet visu kļūdu, tostarp komponentu steku. React 19 dokumentētā hidratācijas kļūda norāda vairākus biežus cēloņus: servera/klienta zari, piemēram, typeof window !== 'undefined', mainīgas vērtības, piemēram, Date.now() vai Math.random(), lokalizācijai atkarīga datuma formatēšana, ārēji dati, kas mainījušies bez momentuzņēmuma, nederīga HTML ievietošana un pārlūka paplašinājumi, kas maina DOM. Skatiet React kļūdu 418.
Next.js sniedz līdzīgu sarakstu savā oficiālajā hidratācijas kļūdu rokasgrāmatā, pievienojot tikai pārlūkam paredzētus API, piemēram, window un localStorage, CSS-in-JS konfigurāciju un HTML, ko modificējis Edge/CDN slānis.
AI ģenerēta ilustrācija: Sašauriniet kļūdu līdz izteiksmei, kas var radīt atšķirīgu vērtību serverī un pārlūkā, piemēram, datumu, nejaušu skaitli, lokalizāciju vai no pārlūka iegūtu vērtību. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Praktiska izolēšanas metode ir īslaicīgi aizstāt aizdomīgas dinamiskas sadaļas ar deterministisku tekstu. Ja kļūda pazūd, atjaunojiet šīs sadaļas pa vienai. Tas parasti ir ātrāk nekā mainīt globālos renderēšanas iestatījumus, pirms zināt, kura komponente ir atbildīga.
Kvalitātes signāls
Jūs varat turpināt, kad varat nosaukt gan kļūdaino komponenti, gan vērtību vai struktūru, kas atšķiras. "Tas notiek kaut kur panelī" joprojām ir pārāk plaši. "StatusCard laika zīmogs tiek ģenerēts neatkarīgi serverī un klientā" ir rīcībspējīga informācija.
2. darbība: Noņemiet nedeterministiskas vērtības no sākotnējā renderējuma
Deterministiska renderēšana nozīmē, ka tie paši ievaddati rada to pašu sākotnējo UI. Vērtības, kas mainās neatkarīgi starp servera renderējumu un pārlūka renderējumu, ir bieži neatbilstību avoti.
Apsveriet šo problemātisko modeli:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
Serveris un pārlūks var palaist šo kodu dažādos brīžos un dažādās lokalizācijās vai laika joslās. Labāks risinājums ir atkarīgs no tā, ko lapai ir jāpaziņo.
Ja laika zīmogs reprezentē servera datus, aprēķiniet vai iegūstiet to vienu reizi serverī un nododiet to pašu serializēto vērtību klientam:
Ja vērtība patiešām ir atkarīga no lietotāja pārlūka, vispirms renderējiet stabilu rezervvieta un atjauniniet to pēc hidratācijas.
AI ģenerēta ilustrācija: Stabilu sākotnējo vērtību var hidratēt bez kļūdām, pēc tam pārlūkam specifisku saturu var piemērot pēc komponentes montēšanas. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Tas darbojas, jo serveris un pirmais klienta renderējums abi rada to pašu rezervvietu. React useEffect dokumentācija apraksta šo divu posmu modeli retos gadījumos, kad klienta saturam ir jāatšķiras no servera satura.
Kad mainīt pieeju
Ja tikai pārlūkam paredzētā vērtība ir visa komponentes mērķis — piemēram, redaktors, kas atjaunots no localStorage, vai logrīks, kas nevar jēgpilni renderēties serverī —, tad rezervvietas un efekta modeļa piespiešana visai komponentei var pievienot nevajadzīgu sarežģītību. Šādā gadījumā izmantojiet apzinātu tikai pārlūkam paredzētu robežu, nevis lieciet, ka komponente ir servera renderējama.
3. darbība: Nelasiet tikai pārlūkam paredzētus API pirmajā servera saderīgajā renderējumā
Bieža nepareiza izpratne Next.js ir tā, ka 'use client' pievienošana garantē, ka komponente renderējas tikai pārlūkā. Tas tā nav. Next.js skaidro, ka Klienta komponentes ir robeža stāvoklim, efektiem, notikumu apstrādātājiem un pārlūka API, taču Klienta komponentes joprojām var piedalīties iepriekšējā renderēšanā. Skatiet pašreizējo use client dokumentāciju.
Serverī localStorage neeksistē. Pat tāds zars kā typeof window !== 'undefined' var radīt atšķirīgu marķējumu pirmajā pārlūka renderējumā, ko gan React, gan Next.js dokumentē kā hidratācijas neatbilstības cēloni.
Mazām atšķirībām pārvietojiet pārlūka lasīšanu uz Efektu. Komponentei, kas Next.js patiešām jābūt tikai pārlūkam paredzētai, to var dinamiski ielādēt, atspējojot SSR:
AI ģenerēta ilustrācija: Izmantojiet tikai klientam paredzētu robežu komponentēm, kas fundamentāli ir atkarīgas no pārlūka API, nevis ļaujiet serverim un pārlūkam renderēt dažādus kokus. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Next.js dokumentē ssr: false Klienta komponentēm savā lazy loading rokasgrāmatā. Tajā pašā rokasgrāmatā teikts, ka ssr: false netiek atbalstīts, ja mēģināt izmantot šo opciju tieši Servera komponentē; pārvietojiet dinamisko importu uz Klienta komponenti.
React 19.3: pirmklasīga tikai pārlūkam paredzēta opcija
React 19.3 ieviesa browser API. Komponente var izsaukt use(browser()) iekš Suspense robežas, lai izslēgtu šo komponenti no servera renderēšanas. Serveris renderē Suspense rezervvietu, savukārt komponente parasti renderējas pārlūkā. Skatiet React browser API atsauces dokumentāciju.
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>
);
}
React Server Components lietojumprogrammā React norāda, ka use(browser()) ir jāizsauc no Klienta komponentes. Pirms šī API ieviešanas arī pārliecinieties, ka jūsu ietvarprogramma un instalētā React versija to nodrošina.
4. darbība: Padariet servera datus un pirmos klienta datus par vienu un to pašu momentuzņēmumu
Momentuzņēmums ir precīzs datu stāvoklis, ko izmanto, lai radītu sākotnējo HTML. Hidratācija kļūst trausla, ja serveris renderē vienu datu versiju, bet klients nekavējoties nolasa jaunāku vai citādā secībā sakārtotu versiju pirms hidratācijas pabeigšanas.
AI ģenerēta ilustrācija: Pirmajam klienta renderējumam ir jāizmanto tas pats sākotnējais datu momentuzņēmums, kas radīja servera HTML; vēlāki atjauninājumi var notikt pēc hidratācijas. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Piemēram, pieņemsim, ka serveris renderē cenu $99, bet klients nekavējoties iegūst to pašu produktu un saņem $109 pirms sava pirmā renderējuma. Problēma nav tā, ka dati mainījās; datu maiņa ir normāla. Problēma ir tā, ka divas vides izmantoja dažādus sākotnējos ievades datus.
Spēcīgs modelis ir:
Iegūstiet sākotnējos datus serverī.
Renderējiet HTML no šiem datiem.
Nododiet vai serializējiet tos pašus sākotnējos datus klienta komponentē.
Pēc hidratācijas ļaujiet klientam validēt un atjaunināt, ja eksistē jaunāki dati.
Pareizā implementācija ir atkarīga no jūsu ietvarprogrammas datu iegūšanas modeļa, taču kvalitātes kritērijs paliek nemainīgs: servera HTML un pirmajam klienta kokam ir jābalstās uz to pašu loģisko stāvokli.
Kad mainīt pieeju
Ja saturs ir pēc savas būtības reāllaika un novecojis servera momentuzņēmums maldinātu lietotājus — piemēram, tiešsaistes tirdzniecības logrīks vai strauji mainīga operāciju konsole —, apsveriet stabilas čaulas renderēšanu serverī un tiešsaistes sadaļas ielādēšanu klientā. Tas upurē daļu servera renderētā satura šim reģionam, taču var būt godīgāk nekā hidratēt pret datiem, kas garantēti mainīsies.
5. darbība: Novērsiet nederīgu HTML, pirms vainojat React
Pārlūkiem ir atļauts labot nepareizi veidotu vai nederīgi ievietotu HTML. Šī labošana var radīt DOM struktūru, kas atšķiras no struktūras, ko React sagaida, pat ja JSX izskatījās vizuāli ticams.
AI ģenerēta ilustrācija: Pārbaudiet semantisko HTML ievietošanu, kad komponentu koks izskatās deterministisks, bet pārlūks joprojām konstruē citu DOM. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Next.js skaidri norāda piemērus, piemēram, <div> iekš <p>, saraksts iekš rindkopas, ievietotas saites un ievietotas pogas kā hidratācijas problēmu cēloņus.
Piemēram, izvairieties no:
<p>
Intro text
<div>Details</div>
</p>
Tā vietā izmantojiet derīgu struktūru:
<div>
<p>Intro text</p>
<div>Details</div>
</div>
Ja komponentu bibliotēka ģenerē marķējumu, pārbaudiet galīgo DOM, nevis pieņemiet, ka ietvara elementi ir derīgi. Lint noteikums vai HTML validators var palīdzēt, taču React hidratē pārlūka faktisko DOM.
6. darbība: Izslēdziet kodu ārpus komponentes
Ja jūsu renderēšanas loģika ir deterministiska un jūsu HTML ir derīgs, pārbaudiet, vai kaut kas nemaina servera HTML, pirms React to hidratē.
Oficiālā Next.js dokumentācija nosauc vairākas iespējas:
Pārlūka paplašinājums maina lapu pirms React ielādējas.
CSS-in-JS bibliotēka ir nepareizi konfigurēta servera renderēšanai.
Edge vai CDN funkcija pārraksta vai minimizē HTML atbildi.
iOS automātiskā tālruņa numuru, e-pasta adreses, datumu vai adreses noteikšana dažos gadījumos var pārvērst tekstu saitēs.
Izmantojiet kontrolētas salīdzināšanas. Testējiet privātā pārlūka logā ar atspējotiem paplašinājumiem. Ja kļūda rodas tikai aiz CDN, salīdziniet ar izcelsmes atbildi. Ja tā sākās pēc stila bibliotēkas ieviešanas, sekojiet šīs bibliotēkas oficiālajai SSR konfigurācijai, nevis piemērojiet vispārīgu hidratācijas risinājumu.
Kvalitātes signāls
Jūs esat izolējis šīs klases problēmu, kad tā pati lietojumprogrammas būve hidratējas pareizi vienā kontrolētā vidē, bet neizdodas pēc tam, kad konkrēts pārlūka paplašinājums, starpniekserveris, CDN transformācija vai integrācija maina HTML.
7. darbība: Izmantojiet suppressHydrationWarning tikai patiešām neizbēgamai lokālai atšķirībai
React nodrošina suppressHydrationWarning={true} retos gadījumos, kad viena elementa teksts vai atribūti nevar saprātīgi sakrist, piemēram, noteikti laika zīmogi.
Tas nav vispārīgs remonta mehānisms. React kopīgo DOM props dokumentācija nosaka, ka opcija darbojas tikai vienu līmeni dziļi un ir paredzēta kā izkļūšanas ceļš. Arī Next.js hidratācijas rokasgrāmata brīdina, ka React nemēģinās labot neatbilstošu teksta saturu, ja šī opcija tiek izmantota.
Izmantojiet to tikai tad, ja ir spēkā visi šie nosacījumi:
Jūs esat apzināti pieņēmis, ka sākotnējā servera vērtība un pārlūka vērtība atšķiras.
Ja propa pievienošana liek pazust desmitiem brīdinājumu, tas ir iemesls turpmākai izpētei, nevis pazīme, ka pamatproblēma ir atrisināta.
8. darbība: Pārbaudiet labojumu izstrādes un produkcijas vidē
AI ģenerēta ilustrācija: Pēc koda maiņas pārbaudiet tīru pārlādēšanu, pareizu interaktivitāti un produkcijas būvi, nevis paļaujieties tikai uz izstrādes pārklājumu. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Izstrādes uzvedība var atšķirties no optimizētas produkcijas būves. Kad kļūda lokāli ir novērsta, veiciet produkcijas stila pārbaudi savai ietvarprogrammai. Tipiskam Next.js projektam tas bieži nozīmē lietojumprogrammas būvēšanu un palaišanu ar jūsu parastajām pakotņu pārvaldnieka komandām, pēc tam veicot jaunas navigācijas un pārlādēšanas.
Izmantojiet šo pārbaudes sarakstu:
Pārbaude
Labs signāls
Ja neizdodas
Jauna pārlādēšana
Nav hidratācijas kļūdas konsolē
Pārbaudiet vēlreiz agrāko atšķirīgo komponenti
Sākotnējais vizuālais stāvoklis
Nav negaidītas mirgošanas vai aizstāšanas
Padariet sākotnējo stāvokli deterministisku
Mijiedarbība
Pogas, formas, izvēlnes un stāvoklis darbojas normāli
Apstipriniet, ka komponente joprojām hidratējas un notikumu apstrādātāji tiek pievienoti
Produkcijas būve
Tas pats pareizais rezultāts kā izstrādē
Izpētiet tikai produkcijas datus, CDN, CSS vai optimizācijas uzvedību
Paplašinājumi atspējoti
Rezultāts nemainās
Identificējiet DOM mainošu paplašinājumu uzvedību
Ja jūs tieši pārvaldāt React SSR ieejas punktu, nevis izmantojat ietvarprogrammu, hydrateRoot atbalsta arī kļūdu atgriezeniskās saites funkcijas, piemēram, onRecoverableError, kas var palīdzēt produkcijas žurnalēšanā. Ietvarprogrammu lietotājiem vispārīgi nevajadzētu aizstāt ietvarprogrammas hidratācijas ieejas punktu tikai tāpēc, lai pievienotu pielāgotu apstrādi.
Kad izmēģināt citu renderēšanas stratēģiju
AI ģenerēta ilustrācija: Mainiet stratēģiju, kad komponente fundamentāli nevar radīt jēgpilnu servera HTML, taču saglabājiet tikai klientam paredzēto robežu pēc iespējas mazāku. Šis nav īsts pārlūka, React vai Next.js ekrānuzņēmums; izmantojiet rakstā norādītās pārbaudītās koda un dokumentācijas saites kā uzticamu avotu.
Dažreiz labākais risinājums nav piespiest komponenti SSR. Apsveriet citu renderēšanas stratēģiju, kad:
Komponente ir izveidota ap window, canvas, WebGL, pārlūka mērījumiem vai citu tikai pārlūkam paredzētu API.
Trešās puses logrīks oficiāli neatbalsta SSR.
Komponentes jēgpilnais saturs pilnībā ir atkarīgs no ierīces lokālā stāvokļa, piemēram, localStorage.
Reāllaika dati mainās tik ātri, ka servera momentuzņēmuma atbilstībai ir maza vērtība.
Šādos gadījumos mērķtiecīga tikai klientam paredzēta robeža var būt tīrāka. Atslēgas vārds ir mērķtiecīga. SSR atspējošana visai lapai, lai pielāgotos vienam grafikam vai redaktorim, var nevajadzīgi upurēt noderīgu servera renderētu saturu, ielādes uzvedību un citas priekšrocības.
Bieži risinājumi, kas izskatās veiksmīgi, bet tādi nav
Īsceļš
Kāpēc tas ir nepilnīgs
Labāks kritērijs
Pievienojiet 'use client' visur
Klienta komponentes Next.js joprojām var tikt iepriekš renderētas
Pārvietojiet tikai pārlūkam paredzēto loģiku pēc hidratācijas vai izolējiet to apzināti
Pats zars var radīt atšķirīgu pirmā renderējuma marķējumu
Saglabājiet pirmo renderējumu identisku
Izmantojiet suppressHydrationWarning plaši
Tas slēpj brīdinājumu, nevis saskaņo lietojumprogrammas stāvokli
Izmantojiet tikai paredzētai, lokālai, neizbēgamai neatbilstībai
Atspējojiet SSR visai lapai
Tas var novērst simptomu, noņemot hidratāciju pārāk lielam UI
Izmantojiet mazāko praktisko tikai klientam paredzēto robežu
Testējiet tikai klienta puses navigāciju
Neatbilstība var parādīties tikai tiešā pieprasījumā vai piespiedu pārlādēšanā
Testējiet jaunas servera renderētas lapas ielādes
Šo risinājumu ierobežojumi
Hidratācijas kļūda norāda, ka servera un klienta renderēšana ir atšķīrusies; tā nepierāda, kāpēc. Tas pats simptoms var rasties no lietojumprogrammas loģikas, pārlūka mutācijas, bibliotēkas, CDN, nepareizi veidota HTML vai mainīgiem datiem. Nav viena koda fragmenta, kas droši novērstu visus šos gadījumus.
Turklāt hidratācijas brīdinājumu noņemšana negarantē pareizību citur. Tikai klientam paredzētai komponentei joprojām var būt datu sacensības. Deterministisks pirmais renderējums joprojām var rādīt novecojušus datus pēc hidratācijas. Derīgs DOM joprojām var saturēt pieejamības problēmas. Uztveriet hidratāciju kā vienu kvalitātes vārtu, nevis vienīgo.
Arī React 19.3 jaunais browser API nenozīmē, ka katrai ietvarprogrammai nekavējoties jāaizstāj tās izveidotā tikai pārlūkam paredzētā modeļa. Ietvarprogrammas integrācija un instalētās versijas ir svarīgas. Ja jūsu projekts izmanto vecāku React vai Next.js izlaidumu, sekojiet šī izlaiduma dokumentācijai, nevis aklām kopējiet jaunāku API.
Uzticama lēmumu secība
Atrodiet mazāko komponenti, kas neatbilst.
Pārbaudiet mainīgas vērtības, piemēram, datumus, nejaušus skaitļus, lokalizācijas formatējumu un divreiz iegūtus datus.
Noņemiet tikai pārlūkam paredzētus API no pirmā servera saderīgā renderējuma.
Nodrošiniet, ka serveris un pirmais klienta renderējums izmanto to pašu datu momentuzņēmumu.
Validējiet HTML struktūru.
Izslēdziet paplašinājumus, CSS-in-JS SSR konfigurāciju un CDN/Edge pārrakstīšanu.
Izmantojiet Efektu, mērķtiecīgu tikai klientam paredzētu renderēšanu vai React 19.3 use(browser()) tikai tad, kad saturs patiešām ir atkarīgs no pārlūka.
Pārbaudiet ar jaunu pārlādēšanu un produkcijas būvi.
Ilgtspējīgs risinājums nav "likt React pārstāt sūdzēties". Tas ir padarīt sākotnējo renderēšanas līgumu skaidru: serverim un pārlūkam ir jāsakrīt par pirmo UI, vai arī tikai pārlūkam paredzētā sadaļa ir apzināti jāizolē, lai React netiktu lūgts hidratēt marķējumu, kas nekad nevarētu sakrist.