Hydration mismatch nghĩa là HTML server sinh ra khác với những gì React dựng ở lần render đầu tại client. Trên dev nó thường im lặng vì React dev sửa lại DOM và chỉ cảnh báo; trên production React bỏ toàn bộ HTML của server và render lại từ đầu ở client — đó là lúc nội dung nhấp nháy, đôi khi trang trắng.
Lý do dev không tái hiện được thường là:
- Dev render mỗi lần một request nên thời gian, dữ liệu luôn mới; production trả HTML tĩnh sinh lúc build rồi client hydrate ở một thời điểm khác.
- Máy dev có cùng timezone/locale với server; người dùng thật thì không.
Các nguồn gây lệch, theo thứ tự hay gặp:
1. new Date().toLocaleString(), Math.random(), Date.now() render thẳng ra JSX.
2. Đọc localStorage/window trong thân component để quyết định render (theme, giỏ hàng, trạng thái đăng nhập).
3. Extension trình duyệt chèn thuộc tính vào DOM.
4. HTML không hợp lệ — <div> bên trong <p>, <tr> không nằm trong <tbody> — trình duyệt tự sắp lại cây khiến DOM khác với cây React.
Cách xử lý:
const [mounted, setMounted] = useState(false)
useEffect(() => setMounted(true), [])
if (!mounted) return <Skeleton /> // render giống nhau ở cả hai phíaVới một node duy nhất và biết chắc lệch là hợp lệ (vd hiển thị thời gian), dùng suppressHydrationWarning.
Để tái hiện lỗi tại máy, chạy next build && next start thay vì next dev — đây là bước đầu tiên nên làm.