Αρχική
» ΒΑΣΙΚΕΣ ΓΝΩΣΕΙΣ
»
Πώς να διορθώσετε το σφάλμα «Hydration failed because the initial UI does not match»
Πώς να διορθώσετε το σφάλμα «Hydration failed because the initial UI does not match»
Το επιθυμητό αποτέλεσμα είναι απλό στην περιγραφή: το HTML που παράγεται στον διακομιστή πρέπει να ταυτίζεται με αυτό που παράγει το React στην πρώτη απόδοση στον browser. Όταν αυτό ισχύει, το React μπορεί να συνδέσει τους χειριστές συμβάντων και να κάνει τη σελίδα διαδραστική χωρίς να προκαλέσει ασυμφωνία hydration, αντικατάσταση υποδέντρου ή απρόσμενη οπτική αλλαγή.
Hydration είναι η διαδικασία κατά την οποία το React λαμβάνει HTML που έχει ήδη αποδοθεί στον διακομιστή και του προσθέτει τη συμπεριφορά του React στον browser. Η τρέχουσα τεκμηρίωση του React για το hydrateRoot αναφέρει ότι το περιεχόμενο που αποδίδεται στον πελάτη αναμένεται να είναι πανομοιότυπο με αυτό που αποδίδεται στον διακομιστή και ότι οι ασυμφωνίες πρέπει να αντιμετωπίζονται ως σφάλματα.
Η ακριβής διατύπωση του σφάλματος έχει αλλάξει σε διάφορες εκδόσεις του React και των frameworks. Μπορεί να δείτε ένα παλαιότερο μήνυμα όπως το "Hydration failed because the initial UI does not match what was rendered on the server", ή ένα νεότερο μήνυμα που εξηγεί ότι το δέντρο που αποδόθηκε στον διακομιστή δεν ταυτιζόταν με αυτό του πελάτη. Η αρχή αποσφαλμάτωσης παραμένει η ίδια.
Το πλαίσιο έκδοσης είναι σημαντικό. Από τις 11 Σεπτεμβρίου 2026, η επίσημη ιστοσελίδα του React αναφέρει το React 19.3 ως την πιο πρόσφατη έκδοση του React, ενώ η τρέχουσα τεκμηρίωση του Next.js αναγνωρίζει το Next.js 16.3.4 ως την πιο πρόσφατη έκδοση του Next.js. Ελέγξτε τη σελίδα εκδόσεων του React και την τρέχουσα τεκμηρίωση του Next.js αν διαβάζετε αυτό το άρθρο αργότερα, καθώς τα διαθέσιμα APIs και τα μηνύματα σφαλμάτων μπορεί να αλλάξουν.
Εικονογράφηση παραγόμενη από AI: Ξεκινήστε εντοπίζοντας το πρώτο component που αναφέρεται στο σφάλμα hydration και επιβεβαιώνοντας ότι το πρόβλημα εμφανίζεται σε μια νέα φόρτωση σελίδας. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Τι θεωρείται επιτυχής διόρθωση;
Μην κρίνετε την επιτυχία μόνο από το αν εξαφανίζεται η κόκκινη επικάλυψη σφαλμάτων στο περιβάλλον development. Μια καλή διόρθωση πρέπει να ικανοποιεί αρκετούς ελέγχους:
Η προειδοποίηση ή το σφάλμα hydration δεν εμφανίζεται πλέον σε μια καθαρή επαναφόρτωση.
Η αρχική διεπαφή χρήστη που αποδίδεται από τον διακομιστή και η πρώτη απόδοση του React στον browser αντιπροσωπεύουν το ίδιο περιεχόμενο και δομή.
Το επηρεαζόμενο component παραμένει διαδραστικό μετά το hydration.
Δεν υπάρχει προφανής αναλαμπή από μια τιμή σε άλλη, εκτός αν αυτή η αλλαγή είναι σκόπιμη και σχεδιασμένη.
Το πρόβλημα παραμένει διορθωμένο σε μια έκδοση production, όχι μόνο στον διακομιστή development.
Έχετε διορθώσει την αιτία αντί να κρύψετε μια πραγματική ασυμφωνία με μια επιλογή απόκρυψης προειδοποιήσεων.
Αν η προειδοποίηση εξαφανίζεται αλλά η σελίδα τώρα αποδίδει σημαντικό περιεχόμενο μόνο μετά τη φόρτωση της JavaScript, το σφάλμα μπορεί να έχει φύγει ενώ η εμπειρία χρήστη έχει επιδεινωθεί. Αυτό μπορεί να είναι μια λογική συμβιβαστική λύση για ένα widget που λειτουργεί μόνο στον browser, αλλά δεν είναι αυτόματα το καλύτερο αποτέλεσμα για το κύριο περιεχόμενο της σελίδας.
Βήμα 1: Αναπαράγετε την ασυμφωνία και βρείτε το μικρότερο component που αποτυγχάνει
Ξεκινήστε με μια σκληρή επαναφόρτωση στο περιβάλλον development και διαβάστε ολόκληρο το σφάλμα, συμπεριλαμβανομένης της στοίβας των components. Η τεκμηριωμένη λίστα σφαλμάτων hydration του React 19 περιλαμβάνει αρκετές κοινές αιτίες: διακλαδώσεις server/client όπως typeof window !== 'undefined', τιμές που αλλάζουν όπως Date.now() ή Math.random(), μορφοποίηση ημερομηνίας που εξαρτάται από την τοπική ρύθμιση (locale), εξωτερικά δεδομένα που άλλαξαν χωρίς στιγμιότυπο, μη έγκυρη ένθεση HTML και επεκτάσεις browser που τροποποιούν το DOM. Δείτε το σφάλμα React 418.
Το Next.js παρέχει μια παρόμοια λίστα στον επίσημο οδηγό σφαλμάτων hydration, προσθέτοντας APIs που υπάρχουν μόνο στον browser όπως window και localStorage, διαμόρφωση CSS-in-JS και HTML που τροποποιείται από ένα επίπεδο Edge/CDN.
Εικονογράφηση παραγόμενη από AI: Στενεύστε το σφάλμα στην έκφραση που μπορεί να παράγει διαφορετική τιμή στον διακομιστή και στον browser, όπως μια ημερομηνία, ένας τυχαίος αριθμός, μια τοπική ρύθμιση ή μια τιμή προερχόμενη από τον browser. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Μια πρακτική μέθοδος απομόνωσης είναι να αντικαταστήσετε προσωρινά τις ύποπτες δυναμικές ενότητες με ντετερμινιστικό κείμενο. Αν το σφάλμα εξαφανιστεί, επαναφέρετε αυτές τις ενότητες μία προς μία. Αυτό είναι συνήθως ταχύτερο από το να αλλάξετε τις καθολικές ρυθμίσεις απόδοσης πριν γνωρίζετε ποιο component ευθύνεται.
Σήμα ποιότητας
Είστε έτοιμοι να προχωρήσετε όταν μπορείτε να ονομάσετε τόσο το component που αποτυγχάνει όσο και την τιμή ή τη δομή που διαφέρει. Το «Συμβαίνει κάπου στο dashboard» είναι ακόμα πολύ ευρύ. Το «Η χρονική σήμανση στο StatusCard παράγεται ανεξάρτητα στον διακομιστή και τον πελάτη» είναι κάτι που μπορείτε να δράσετε επάνω του.
Βήμα 2: Αφαιρέστε μη ντετερμινιστικές τιμές από την αρχική απόδοση
Η ντετερμινιστική απόδοση σημαίνει ότι οι ίδιες εισόδους παράγουν την ίδια αρχική διεπαφή χρήστη. Οι τιμές που αλλάζουν ανεξάρτητα μεταξύ της απόδοσης στον διακομιστή και της απόδοσης στον browser είναι συχνές πηγές ασυμφωνίας.
Θεωρήστε αυτό το προβληματικό μοτίβο:
export default function LastUpdated() {
return <time>{new Date().toLocaleString()}</time>;
}
Ο διακομιστής και ο browser μπορεί να εκτελούν αυτόν τον κώδικα σε διαφορετικές στιγμές και σε διαφορετικές τοπικές ρυθμίσεις ή ζώνες ώρας. Μια καλύτερη λύση εξαρτάται από το τι πρέπει να επικοινωνήσει η σελίδα.
Αν η χρονική σήμανση αντιπροσωπεύει δεδομένα του διακομιστή, υπολογίστε ή ανακτήστε τα μία φορά στον διακομιστή και περάστε την ίδια σειριοποιημένη τιμή στον πελάτη:
Αν η τιμή εξαρτάται πραγματικά από τον browser του χρήστη, αποδώστε πρώτα μια σταθερή θέση κράτησης (placeholder) και ενημερώστε την μετά το hydration.
Εικονογράφηση παραγόμενη από AI: Μια σταθερή αρχική τιμή μπορεί να κάνει hydration καθαρά, και στη συνέχεια το περιεχόμενο ειδικό για τον browser μπορεί να εφαρμοστεί μετά την τοποθέτηση του component. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Αυτό λειτουργεί επειδή ο διακομιστής και η πρώτη απόδοση στον πελάτη παράγουν και τα δύο την ίδια θέση κράτησης. Η τεκμηρίωση του React για το useEffect περιγράφει αυτό το μοτίβο δύο σταδίων για τις σπάνιες περιπτώσεις όπου το περιεχόμενο του πελάτη πρέπει να διαφέρει από αυτό του διακομιστή.
Πότε να αλλάξετε προσέγγιση
Αν η τιμή που υπάρχει μόνο στον browser είναι ολόκληρος ο σκοπός του component—for παράδειγμα, ένας επεξεργαστής κειμένου που αποκαθίσταται από το localStorage ή ένα widget που δεν μπορεί να αποδοθεί ουσιαστικά στον διακομιστή—η επιβολή ενός μοτίβου placeholder-and-effect σε όλο το component μπορεί να προσθέσει περιττή πολυπλοκότητα. Σε αυτή την περίπτωση, χρησιμοποιήστε ένα σκόπιμο όριο μόνο για τον browser αντί να προσποιείστε ότι το component είναι αποδοτέο από τον διακομιστή.
Βήμα 3: Μην διαβάζετε APIs που υπάρχουν μόνο στον browser κατά την πρώτη απόδοση συμβατή με τον διακομιστή
Μια κοινή παρανόηση στο Next.js είναι ότι η προσθήκη 'use client' εγγυάται ότι το component αποδίδεται μόνο στον browser. Δεν το κάνει. Το Next.js εξηγεί ότι τα Client Components αποτελούν το όριο για την κατάσταση, τα effects, τους χειριστές συμβάντων και τα APIs του browser, αλλά τα Client Components μπορούν ακόμα να συμμετέχουν στην προ-απόδοση (prerendering). Δείτε την τρέχουσα τεκμηρίωση για το use client.
Στον διακομιστή, το localStorage δεν υπάρχει. Ακόμα και μια διακλάδωση όπως typeof window !== 'undefined' μπορεί να παράγει διαφορετικό markup στην πρώτη απόδοση στον browser, κάτι που τόσο το React όσο και το Next.js τεκμηριώνουν ως αιτία ασυμφωνίας hydration.
Για μικρές διαφορές, μετακινήστε την ανάγνωση του browser σε ένα Effect. Για ένα component που πρέπει πραγματικά να είναι μόνο για τον browser στο Next.js, μπορείτε να το φορτώσετε δυναμικά με απενεργοποιημένο SSR:
Εικονογράφηση παραγόμενη από AI: Χρησιμοποιήστε ένα όριο μόνο για τον πελάτη για components που εξαρτώνται θεμελιωδώς από APIs του browser, αντί να αφήσετε τον διακομιστή και τον browser να αποδώσουν διαφορετικά δέντρα. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Το Next.js τεκμηριώνει το ssr: false για τα Client Components στον οδηγό φορτίου με καθυστέρηση (lazy loading). Ο ίδιος οδηγός αναφέρει ότι το ssr: false δεν υποστηρίζεται όταν προσπαθείτε να χρησιμοποιήσετε αυτή την επιλογή απευθείας σε ένα Server Component· μετακινήστε τη δυναμική εισαγωγή σε ένα Client Component.
React 19.3: μια πρωτογενής επιλογή μόνο για τον browser
Το React 19.3 εισήγαγε το API browser. Ένα component μπορεί να καλέσει use(browser()) μέσα σε ένα όριο Suspense για να εξαιρέσει αυτό το component από την απόδοση στον διακομιστή. Ο διακομιστής αποδίδει το fallback του Suspense, ενώ το component αποδίδεται κανονικά στον browser. Δείτε την αναφορά API browser του 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>
);
}
Σε μια εφαρμογή React Server Components, το React αναφέρει ότι το use(browser()) πρέπει να καλείται από ένα Client Component. Επίσης, επαληθεύστε ότι το framework σας και η εγκατεστημένη έκδοση React εκθέτουν αυτό το API πριν το υιοθετήσετε.
Βήμα 4: Κάντε τα δεδομένα του διακομιστή και τα πρώτα δεδομένα του πελάτη το ίδιο στιγμιότυπο
Ένα στιγμιότυπο (snapshot) είναι η ακριβής κατάσταση των δεδομένων που χρησιμοποιήθηκε για την παραγωγή του αρχικού HTML. Το hydration γίνεται εύθραυστο αν ο διακομιστής αποδίδει μια έκδοση δεδομένων και ο πελάτης διαβάζει αμέσως μια νεότερη ή διαφορετικά ταξινομημένη έκδοση πριν ολοκληρωθεί το hydration.
Εικονογράφηση παραγόμενη από AI: Η πρώτη απόδοση στον πελάτη πρέπει να καταναλώνει το ίδιο αρχικό στιγμιότυπο δεδομένων που παρήγαγε το HTML του διακομιστή· οι μεταγενέστερες ενημερώσεις μπορούν να συμβούν μετά το hydration. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Για παράδειγμα, υποθέστε ότι ο διακομιστής αποδίδει μια τιμή 99 δολαρίων, αλλά ο πελάτης ανακτά αμέσως το ίδιο προϊόν και λαμβάνει 109 δολάρια πριν από την πρώτη του απόδοση. Το πρόβλημα δεν είναι ότι τα δεδομένα άλλαξαν· η αλλαγή δεδομένων είναι φυσιολογική. Το πρόβλημα είναι ότι τα δύο περιβάλλοντα χρησιμοποίησαν διαφορετικές αρχικές εισόδους.
Ένα ισχυρό μοτίβο είναι:
Ανακτήστε τα αρχικά δεδομένα στον διακομιστή.
Αποδώστε το HTML από αυτά τα δεδομένα.
Περάστε ή σειριοποιήστε τα ίδια αρχικά δεδομένα στο component του πελάτη.
Μετά το hydration, επιτρέψτε στον πελάτη να επανυπολογίσει και να ενημερώσει αν υπάρχουν νεότερα δεδομένα.
Η σωστή υλοποίηση εξαρτάται από το μοντέλο ανάκτησης δεδομένων του framework σας, αλλά το κριτήριο ποιότητας παραμένει το ίδιο: το HTML του διακομιστή και το πρώτο δέντρο του πελάτη πρέπει να βασίζονται στην ίδια λογική κατάσταση.
Πότε να αλλάξετε προσέγγιση
Αν το περιεχόμενο είναι εγγενώς σε πραγματικό χρόνο και ένα παλιό στιγμιότυπο του διακομιστή θα παραπλανούσε τους χρήστες—for παράδειγμα, ένα widget ζωντανών συναλλαγών ή μια κονσόλα λειτουργιών που αλλάζει ραγδαία—θεωρήστε την απόδοση ενός σταθερού κελύφους στον διακομιστή και τη φόρτωση της ζωντανής ενότητας στον πελάτη. Αυτό θυσιάζει λίγο περιεχόμενο αποδοτέο από τον διακομιστή για αυτή την περιοχή, αλλά μπορεί να είναι πιο ειλικρινές από το να κάνετε hydration με δεδομένα που είναι εγγυημένα ότι θα αλλάξουν.
Βήμα 5: Διορθώστε το μη έγκυρο HTML πριν κατηγορήσετε το React
Οι browsers επιτρέπεται να διορθώνουν κακοσχηματισμένο ή μη έγκυρα ένθετο HTML. Αυτή η διόρθωση μπορεί να παράγει μια δομή DOM που διαφέρει από τη δομή που περιμένει το React, ακόμα και όταν το JSX φαινόταν οπτικά εύλογο.
Εικονογράφηση παραγόμενη από AI: Ελέγξτε τη σημασιολογική ένθεση HTML όταν το δέντρο των components φαίνεται ντετερμινιστικό αλλά ο browser εξακολουθεί να κατασκευάζει ένα διαφορετικό DOM. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Το Next.js παραθέτει ρητά παραδείγματα όπως ένα <div> μέσα σε ένα <p>, μια λίστα μέσα σε μια παράγραφο, ένθετοι σύνδεσμοι (anchors) και ένθετα κουμπιά ως αιτίες προβλημάτων hydration.
Για παράδειγμα, αποφύγετε:
<p>
Intro text
<div>Details</div>
</p>
Χρησιμοποιήστε αντίθετα μια έγκυρη δομή:
<div>
<p>Intro text</p>
<div>Details</div>
</div>
Αν μια βιβλιοθήκη components παράγει το markup, επιθεωρήστε το τελικό DOM αντί να υποθέτετε ότι τα στοιχεία περιτύλιξης είναι έγκυρα. Ένας κανόνας lint ή ένας επικυρωτής HTML μπορεί να βοηθήσει, αλλά το πραγματικό DOM του browser είναι αυτό που κάνει hydration το React.
Βήμα 6: Αποκλείστε κώδικα εκτός του component
Αν η λογική απόδοσής σας είναι ντετερμινιστική και το HTML σας είναι έγκυρο, ελέγξτε αν κάτι τροποποιεί το HTML του διακομιστή πριν το κάνει hydration το React.
Η επίσημη τεκμηρίωση του Next.js ονομάζει αρκετές πιθανότητες:
Μια επέκταση browser αλλάζει τη σελίδα πριν φορτώσει το React.
Μια βιβλιοθήκη CSS-in-JS είναι λανθασμένα διαμορφωμένη για απόδοση στον διακομιστή.
Μια λειτουργία Edge ή CDN ξαναγράφει ή συμπιέζει την απόκριση HTML.
Στο iOS, η αυτόματη ανίχνευση αριθμών τηλεφώνου, διευθύνσεων email, ημερομηνιών ή διευθύνσεων μπορεί να μετατρέψει το κείμενο σε συνδέσμους σε ορισμένες περιπτώσεις.
Χρησιμοποιήστε ελεγχόμενες συγκρίσεις. Δοκιμάστε σε ένα παράθυρο browser ιδιωτικής περιήγησης με απενεργοποιημένες επεκτάσεις. Αν το σφάλμα εμφανίζεται μόνο πίσω από ένα CDN, συγκρίνετε με την απόκριση της προέλευσης (origin). Αν ξεκίνησε μετά την υιοθέτηση μιας βιβλιοθήκης στυλ, ακολουθήστε την επίσημη διαμόρφωση SSR της βιβλιοθήκης αντί να εφαρμόσετε μια γενική λύση για το hydration.
Σήμα ποιότητας
Έχετε απομονώσει αυτή την κατηγορία προβλήματος όταν η ίδια έκδοση της εφαρμογής κάνει hydration σωστά σε ένα ελεγχόμενο περιβάλλον αλλά αποτυγχάνει μετά που μια συγκεκριμένη επέκταση browser, proxy, μετασχηματισμός CDN ή ολοκλήρωση αλλάζει το HTML.
Βήμα 7: Χρησιμοποιήστε το suppressHydrationWarning μόνο για μια πραγματικά αναπόφευκτη τοπική διαφορά
Το React παρέχει το suppressHydrationWarning={true} για σπάνιες περιπτώσεις όπου το κείμενο ή τα χαρακτηριστικά ενός μόνο στοιχείου δεν μπορούν λογικά να ταυτιστούν, όπως ορισμένες χρονικές σήμανσεις.
Αυτό δεν είναι ένας γενικός μηχανισμός επισκευής. Η τεκμηρίωση των κοινών DOM props του React αναφέρει ότι η επιλογή λειτουργεί μόνο ένα επίπεδο βάθος και προορίζεται ως έξοδος έκτακτης ανάγκης. Ο οδηγός hydration του Next.js προειδοποιεί επίσης ότι το React δεν θα προσπαθήσει να διορθώσει μη ταυτιζόμενο περιεχόμενο κειμένου όταν χρησιμοποιείται αυτή η επιλογή.
Χρησιμοποιήστε το μόνο όταν ισχύουν όλα τα παρακάτω:
Η διαφορά είναι αναμενόμενη και εντοπισμένη.
Η ασυμφωνία δεν αντιπροσωπεύει λανθασμένη κατάσταση της εφαρμογής.
Η γύρω δομή είναι σταθερή.
Έχετε συνειδητά αποδεχτεί ότι η αρχική τιμή του διακομιστή και η τιμή του browser διαφέρουν.
Αν η προσθήκη της ιδιότητας κάνει δεκάδες προειδοποιήσεις να εξαφανιστούν, αυτός είναι ένας λόγος για περαιτέρω διερεύνηση, όχι ένα σημάδι ότι το υποκείμενο πρόβλημα έχει λυθεί.
Βήμα 8: Επαληθεύστε τη διόρθωση σε Development και Production
Εικονογράφηση παραγόμενη από AI: Μετά την αλλαγή του κώδικα, επαληθεύστε μια καθαρή επαναφόρτωση, σωστή διαδραστικότητα και μια έκδοση production αντί να βασίζεστε μόνο στην επικάλυψη development. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Η συμπεριφορά στο development μπορεί να διαφέρει από μια βελτιστοποιημένη έκδοση production. Αφού το σφάλμα έχει φύγει τοπικά, εκτελέστε έναν έλεγχο τύπου production για το framework σας. Για ένα τυπικό έργο Next.js, αυτό συχνά σημαίνει την οικοδόμηση και την εκκίνηση της εφαρμογής με τις κανονικές εντολές του package manager σας, και στη συνέχεια την εκτέλεση νέων πλοήγησης και επαναφορτώσεων.
Χρησιμοποιήστε αυτή την λίστα ελέγχου επαλήθευσης:
Έλεγχος
Καλό σημάδι
Αν αποτύχει
Νέα επαναφόρτωση
Κανένα σφάλμα hydration στην κονσόλα
Ελέγξτε ξανά το πρώτο component που διαφέρει
Αρχική οπτική κατάσταση
Καμία ανεπιθύμητη αναλαμπή ή αντικατάσταση
Κάντε την αρχική κατάσταση ντετερμινιστική
Αλληλεπιδράσεις
Τα κουμπιά, οι φόρμες, τα μενού και η κατάσταση λειτουργούν κανονικά
Επιβεβαιώστε ότι το component κάνει ακόμα hydration και οι χειριστές συμβάντων συνδέονται
Έκδοση Production
Το ίδιο σωστό αποτέλεσμα με το development
Διερευνήστε δεδομένα μόνο για production, CDN, CSS ή συμπεριφορά βελτιστοποίησης
Απενεργοποιημένες επεκτάσεις
Το αποτέλεσμα δεν αλλάζει
Εντοπίστε συμπεριφορά επεκτάσεων που τροποποιούν το DOM
Αν κατέχετε άμεσα το σημείο εισόδου React SSR αντί να χρησιμοποιείτε ένα framework, το hydrateRoot υποστηρίζει επίσης回调s σφαλμάτων όπως το onRecoverableError, το οποίο μπορεί να βοηθήσει στην καταγραφή στο production. Οι χρήστες framework γενικά δεν πρέπει να αντικαθιστούν το σημείο εισόδου hydration του framework μόνο για να προσθέσουν προσαρμοσμένη διαχείριση.
Πότε να δοκιμάσετε μια διαφορετική στρατηγική απόδοσης
Εικονογράφηση παραγόμενη από AI: Αλλάξτε στρατηγική όταν ένα component δεν μπορεί θεμελιωδώς να παράγει ουσιαστικό HTML διακομιστή, αλλά κρατήστε το όριο μόνο για τον πελάτη όσο το δυνατόν μικρότερο. Δεν πρόκειται για πραγματικό στιγμιότυπο οθόνης browser, React ή Next.js· χρησιμοποιήστε τους επαληθευμένους συνδέσμους κώδικα και τεκμηρίωσης στο άρθρο ως πηγή αλήθειας.
Μερικές φορές η καλύτερη διόρθωση δεν είναι να αναγκάσετε ένα component σε SSR. Θεωρήστε μια διαφορετική στρατηγική απόδοσης όταν:
Το component είναι χτισμένο γύρω από το window, canvas, WebGL, μετρήσεις browser ή άλλο API μόνο για τον browser.
Ένα widget τρίτου μέρους δεν υποστηρίζει επίσημα το SSR.
Το ουσιαστικό περιεχόμενο του component εξαρτάται εξ ολοκλήρου από την τοπική κατάσταση της συσκευής όπως το localStorage.
Τα δεδομένα σε πραγματικό χρόνο αλλάζουν τόσο γρήγορα που η ταύτιση με ένα στιγμιότυπο του διακομιστή έχει little value.
Σε αυτές τις περιπτώσεις, ένα στοχευμένο όριο μόνο για τον πελάτη μπορεί να είναι πιο καθαρό. Η λέξη-κλειδί είναι στοχευμένο. Η απενεργοποίηση του SSR για ολόκληρη τη σελίδα για να εξυπηρετηθεί ένα γράφημα ή ένας επεξεργαστής μπορεί να θυσιάσει χρήσιμο περιεχόμενο αποδοτέο από τον διακομιστή, συμπεριφορά φόρτωσης και άλλα οφέλη χωρίς λόγο.
Κοινές διορθώσεις που φαίνονται επιτυχείς αλλά δεν είναι
Συντόμευση
Γιατί είναι ελλιπής
Καλύτερο κριτήριο
Προσθήκη 'use client' παντού
Τα Client Components μπορούν ακόμα να προ-αποδοθούν στο Next.js
Μετακινήστε τη λογική μόνο για τον browser μετά το hydration ή απομονώστε τη σκόπιμα
Περιτύλιξη της λογικής απόδοσης σε typeof window !== 'undefined'
Η διακλάδωση本身 μπορεί να δημιουργήσει διαφορετικό markup πρώτης απόδοσης
Κρατήστε την πρώτη απόδοση πανομοιότυπη
Χρήση του suppressHydrationWarning ευρέως
Κρύβει μια προειδοποίηση αντί να συμβιβάζει την κατάσταση της εφαρμογής
Χρησιμοποιήστε μόνο για μια αναμενόμενη, τοπική, αναπόφευκτη ασυμφωνία
Απενεργοποίηση SSR για ολόκληρη τη σελίδα
Μπορεί να αφαιρέσει το σύμπτωμα αφαιρώντας το hydration για πολύ UI
Χρησιμοποιήστε το μικρότερο πρακτικό όριο μόνο για τον πελάτη
Δοκιμή μόνο πλοήγησης στον πελάτη
Μια ασυμφωνία μπορεί να εμφανιστεί μόνο σε ένα άμεσο αίτημα ή σκληρή επαναφόρτωση
Δοκιμάστε νέες φορτώσεις σελίδας αποδοτέες από τον διακομιστή
Όρια αυτών των διορθώσεων
Ένα σφάλμα hydration σας λέει ότι η απόδοση του διακομιστή και του πελάτη αποκλίνουν· δεν αποδεικνύει γιατί. Το ίδιο σύμπτωμα μπορεί να προέρχεται από τη λογική της εφαρμογής, μεταλλάξεις του browser, μια βιβλιοθήκη, ένα CDN, κακοσχηματισμένο HTML ή δεδομένα που αλλάζουν. Δεν υπάρχει ένα μόνο απόσπασμα κώδικα που να διορθώνει με ασφάλεια όλες αυτές τις περιπτώσεις.
Επίσης, η αφαίρεση των προειδοποιήσεων hydration δεν εγγυάται την ορθότητα αλλού. Ένα component μόνο για τον πελάτη μπορεί ακόμα να έχει αγώνες δεδομένων (data races). Μια ντετερμινιστική πρώτη απόδοση μπορεί ακόμα να δείχνει παλιά δεδομένα μετά το hydration. Ένα έγκυρο DOM μπορεί ακόμα να περιέχει προβλήματα προσβασιμότητας. Θεωρήστε το hydration ως μία πύλη ποιότητας, όχι τη μόνη.
Το νέο API browser του React 19.3 επίσης δεν σημαίνει ότι κάθε framework πρέπει αμέσως να αντικαταστήσει το καθιερωμένο του μοτίβο μόνο για τον browser. Η ενσωμάτωση του framework και οι εγκατεστημένες εκδόσεις είναι σημαντικές. Αν το έργο σας βρίσκεται σε μια παλαιότερη έκδοση React ή Next.js, ακολουθήστε την τεκμηρίωση για αυτή την έκδοση αντί να αντιγράψετε τυφλά ένα νεότερο API.
Μια αξιόπιστη σειρά αποφάσεων
Εντοπίστε το μικρότερο component που ασυμφωνεί.
Ελέγξτε για τιμές που αλλάζουν όπως ημερομηνίες, τυχαίους αριθμούς, μορφοποίηση locale και δεδομένα που ανακτώνται δύο φορές.
Αφαιρέστε APIs μόνο για τον browser από την πρώτη απόδοση συμβατή με τον διακομιστή.
Εξασφαλίστε ότι ο διακομιστής και η πρώτη απόδοση στον πελάτη χρησιμοποιούν το ίδιο στιγμιότυπο δεδομένων.
Επικυρώστε τη δομή HTML.
Αποκλείστε επεκτάσεις, διαμόρφωση SSR CSS-in-JS και ξαναγραφή CDN/Edge.
Χρησιμοποιήστε ένα Effect, στοχευμένη απόδοση μόνο για τον πελάτη ή το use(browser()) του React 19.3 μόνο όταν το περιεχόμενο εξαρτάται πραγματικά από τον browser.
Φυλάξτε το suppressHydrationWarning για μικρές, σκόπιμες ασυμφωνίες.
Επαληθεύστε με μια νέα επαναφόρτωση και μια έκδοση production.
Η διαρκής διόρθωση δεν είναι «να κάνετε το React να σταματήσει να παραπονιέται». Είναι να κάνετε τη σύμβαση αρχικής απόδοσης ρητή: ο διακομιστής και ο browser πρέπει να συμφωνούν στην πρώτη διεπαφή χρήστη, ή η ενότητα μόνο για τον browser πρέπει να είναι σκόπιμα απομονωμένη ώστε το React να μην καλείται να κάνει hydration markup που δεν θα μπορούσε ποτέ να ταυτιστεί.