Hydration mismatch nghĩa là HTML server sinh ra khác với cây React client dựng ở lần render đầu. React 18 trở đi sẽ vứt HTML của vùng đó và render lại từ client, kèm cảnh báo — kết quả là chậm và có thể nhấp nháy.
Bốn nhóm nguyên nhân và cách xử lý:
1. Giá trị thay đổi theo thời điểm — Date.now(), new Date().toLocaleString(), Math.random(), crypto.randomUUID(). Render một giá trị ổn định ở lần đầu, cập nhật trong useEffect; id thì dùng useId.
2. Đọc API chỉ có ở trình duyệt trong render — window, localStorage, matchMedia. Server không có nên ra nhánh khác. Đọc trong useEffect, hoặc dùng useSyncExternalStore với getServerSnapshot.
3. Khác biệt do múi giờ hoặc locale giữa server và máy người dùng. Format ở client, hoặc chốt cứng timezone/locale cho cả hai phía.
4. HTML không hợp lệ — <div> nằm trong <p>, <td> không có <tr>. Trình duyệt tự sửa cấu trúc khi parse, React so ra lệch. Sửa lại markup cho đúng.
Ngoài ra extension trình duyệt chèn thẻ vào <body> cũng gây cảnh báo — đây là trường hợp bỏ qua được.
suppressHydrationWarning chỉ tắt cảnh báo cho một node (hợp lý với dấu thời gian), không sửa được sai lệch. Dùng nó để giấu mọi lỗi là sai hướng.