Lỗi Hydration trong Next.js: Nguyên nhân và Cách khắc phục
Nếu bạn đã làm việc với Next.js, có lẽ bạn đã thấy cảnh báo này xuất hiện ít nhất một lần:
Cảnh báo: Nội dung văn bản không khớp với HTML được render trên server.
Đây là lỗi Hydration nổi tiếng.
Lần đầu tiên tôi thấy lỗi này, tôi đã tự hỏi: “Chờ đã, ứng dụng của tôi vẫn hoạt động... vậy tại sao lỗi này lại kêu la như vậy?”
Và rồi, dự án này sang dự án khác, lỗi này vẫn xuất hiện.
Hóa ra, đây là một trong những rào cản phổ biến nhất đối với những ai chuyển từ React sang Next.js.
Tin tốt là? Một khi bạn hiểu tại sao, việc khắc phục trở nên đơn giản.
🔎 Tại sao điều này xảy ra?
Hydration = kết nối HTML được render trên server với React ở client.
Nếu nội dung mà server xuất ra không hoàn toàn khớp với những gì React mong đợi → lỗi hydration.
Đây không phải là ngẫu nhiên. Next.js chỉ đang nói: “Này, có điều gì đó khác biệt ở đây.”
Những nguyên nhân thường gặp:
- Sử dụng
window
/document
trên server (cái này không tồn tại trong SSR) - Giá trị thay đổi giữa các lần render (
Math.random()
,Date.now()
) - Điều kiện render hành xử khác nhau trên server và client
- Các thành phần bên thứ ba không an toàn cho SSR
✅ Cách tôi khắc phục
Dưới đây là các giải pháp đã hoạt động mỗi khi tôi gặp lỗi:
- Chạy mã chỉ dành cho trình duyệt trong
useEffect
javascript
// ❌ Sai
const width = window.innerWidth;
// ✅ Đúng
const [width, setWidth] = useState<number | null>(null);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
- Sử dụng import động cho các thành phần chỉ dành cho client
javascript
import dynamic from "next/dynamic";
const Chart = dynamic(() => import("../components/Chart"), { ssr: false });
-
Giữ cho lần render ban đầu nhất quán
Nếu bạn hiển thị các placeholder/spinner, hãy chắc chắn rằng chúng được render giống nhau trên cả server và client trước khi React tiếp quản. -
Kiểm tra các thư viện của bạn
Không phải mọi gói npm đều được xây dựng với SSR trong tâm trí. Sử dụng các lựa chọn thay thế hoặc tải chúng một cách động. -
Gỡ lỗi thông minh
So sánh những gì được render trên server và client — sự không khớp đó là nơi lỗi bắt đầu.
🚀 Thực hành tốt nhất để tránh lỗi hydration
- Chỉ render có thể dự đoán. Đừng sử dụng các giá trị thay đổi giữa các lần render.
- Phân tách logic an toàn cho SSR và chỉ dành cho client sớm. Nghĩ: Liệu điều này có thể chạy trên server không?
- Sử dụng
useEffect
và import động. Đây là công cụ bạn nên sử dụng. - Cẩn thận với điều kiện render. Cả server và client phải đồng ý về đầu ra ban đầu.
- Kiểm tra với các bản build sản xuất (
next build && next start
). Một số vấn đề hydration không xuất hiện trong chế độ phát triển.
💡 Kết luận
Lỗi hydration không phải là lỗi ngẫu nhiên. Chúng thực sự là tín hiệu cho bạn biết rằng có điều gì đó không thân thiện với SSR.
Khi bạn hiểu chúng, bạn sẽ thấy các ứng dụng Next.js của mình trở nên ổn định, dự đoán được và sẵn sàng cho sản xuất.
💬 Đến lượt bạn
Lỗi hydration có làm bạn phát điên chưa?
Bạn đã khắc phục chúng như thế nào? Hay có thể... bạn vẫn đang chiến đấu với chúng? 😅
Hãy chia sẻ câu chuyện của bạn — cùng nhau chúng ta sẽ làm cho lỗi này bớt đáng sợ hơn.