April 1, 2025

Hydration trong Next.js: Hiểu và tránh lỗi common
Giải thích về hydration trong Next.js và cách tránh các lỗi thường gặp
Hydration trong Next.js là gì?
Hydration là quá trình Next.js sử dụng để kết nối mã JavaScript chạy trên client với HTML đã được render trước đó từ server. Quá trình này giúp React tiếp quản UI mà không cần render lại toàn bộ trang.
Tuy nhiên, nếu không được quản lý đúng cách, hydration có thể gây ra lỗi và ảnh hưởng đến hiệu suất.
1. Hydration Mismatch
Lỗi này xảy ra khi HTML render từ server khác với HTML mà React render trên client. Nguyên nhân phổ biến là sử dụng dữ liệu thay đổi theo thời gian như số ngẫu nhiên, ngày giờ hoặc các API không đồng bộ trong quá trình render trên server.
export default function Page() {
return <p>{Math.random()}</p>;
}
Cách khắc phục:
- Tránh sử dụng dữ liệu thay đổi theo thời gian trong quá trình render trên server.
- Nếu cần dữ liệu động, hãy cập nhật sau khi component mount.
2. Truy cập vào các API của browser trên server
Server không có window
, document
, hoặc localStorage
, vì vậy nếu code cố truy cập chúng trong quá trình render, sẽ xảy ra lỗi.
import { useState, useEffect } from "react";
export default function Page() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <p>Width: {width}</p>;
}
Cách khắc phục:
- Chỉ truy cập API của browser sau khi component đã mount.
- Sử dụng các hooks như
useEffect
để xử lý logic liên quan đến browser.
3. Quên thêm 'use client'
khi cần
Mặc định, các component trong thư mục app/
của Next.js 13+ là Server Components. Nếu một component cần dùng useState
, useEffect
, hoặc event listeners mà không có 'use client'
, nó sẽ gây lỗi.
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
Cách khắc phục:
- Thêm
'use client'
vào đầu file nếu component cần trạng thái hoặc sự kiện người dùng. - Phân biệt rõ ràng giữa Server Components và Client Components.
4. Quá nhiều Client Components làm mất lợi thế của Server Components
Một số dev đặt 'use client'
lên toàn bộ ứng dụng, khiến Next.js mất đi lợi ích của Server Components, làm tăng kích thước JavaScript tải xuống.
Cách khắc phục:
- Chỉ sử dụng
'use client'
khi thật sự cần. - Giữ các thành phần tĩnh như layout, navigation dưới dạng Server Components.
5. Cách tránh lỗi Hydration
- Tránh dữ liệu thay đổi theo thời gian trong quá trình render trên server.
- Không sử dụng API của browser trong Server Components.
- Chỉ thêm
'use client'
cho component cần interactivity. - Kết hợp Server Components và Client Components hợp lý.
Hydration là một phần quan trọng trong Next.js, nhưng nếu không hiểu rõ, nó có thể gây ra lỗi và ảnh hưởng đến hiệu suất. Hãy tối ưu code để tránh những vấn đề trên và tận dụng tối đa sức mạnh của Next.js!
Hydration in Next.js: Understanding and Avoiding Common Errors
An explanation of hydration in Next.js and how to avoid common errors
What is Hydration in Next.js?
Hydration is the process that Next.js uses to connect the JavaScript code running on the client with the HTML that was previously rendered from the server. This process allows React to take over the UI without having to re-render the entire page.
However, if not managed correctly, hydration can cause errors and impact performance.
1. Hydration Mismatch
This error occurs when the HTML rendered from the server is different from the HTML that React renders on the client. Common causes include using time-sensitive data like random numbers, dates, or asynchronous APIs during server-side rendering.
export default function Page() {
return <p>{Math.random()}</p>;
}
How to fix:
- Avoid using time-sensitive data during server-side rendering.
- If dynamic data is needed, update it after the component mounts.
2. Accessing Browser APIs on the Server
The server does not have access to window
, document
, or localStorage
, so if the code tries to access these during rendering, an error will occur.
import { useState, useEffect } from "react";
export default function Page() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <p>Width: {width}</p>;
}
How to fix:
- Only access browser APIs after the component has mounted.
- Use hooks like
useEffect
to handle logic related to the browser.
3. Forgetting to add 'use client'
when needed
By default, components in the app/
directory of Next.js 13+ are Server Components. If a component needs to use useState
, useEffect
, or event listeners without 'use client'
, it will cause an error.
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
How to fix:
- Add
'use client'
at the beginning of the file if the component needs state or user events. - Clearly distinguish between Server Components and Client Components.
4. Too many Client Components causing loss of Server Components benefits
Some developers apply 'use client'
across the entire application, causing Next.js to lose the benefits of Server Components, which increases the JavaScript bundle size.
How to fix:
- Only use
'use client'
when necessary. - Keep static components like layout and navigation as Server Components.
5. How to avoid Hydration errors
- Avoid time-sensitive data during server-side rendering.
- Do not use browser APIs in Server Components.
- Only add
'use client'
for components that need interactivity. - Use a good balance between Server Components and Client Components.
Hydration is an important part of Next.js, but if not properly understood, it can lead to errors and performance issues. Optimize your code to avoid these problems and take full advantage of Next.js!