Hôm nay, mình sẽ giúp bạn giải mã câu hỏi muôn thuở khi làm việc với Next.js: Khi nào dùng Server Component, khi nào dùng Client Component? Mình sẽ giữ mọi thứ ngắn gọn, dễ hiểu, thêm chút hài hước cho vui, và kèm ví dụ code thực tế từ những ngày “vật lộn” với dự án. Let’s go!
Server Component và Client Component là gì?
Trước hết, cần hiểu rõ hai “nhân vật” này trong Next.js (App Router)
Server Component: Được render trên server, chuyên xử lý các công việc “nặng đô” như lấy dữ liệu từ API, truy cập backend, hay làm mấy thứ bí mật không muốn client thấy. Hãy tưởng tượng nó như đầu bếp trong nhà hàng – nấu nướng ngon lành nhưng không ra tiếp khách.
Client Component: Render trên trình duyệt, là “ngôi sao” của interactivity – xử lý click, form, hay bất cứ thứ gì cần tương tác với người dùng. Nó giống như anh phục vụ – giao tiếp với khách hàng, nhận order, và làm mọi thứ sinh động.
Mặc định, mọi component trong Next.js là Server Component, trừ khi bạn thêm ‘use client’ để biến nó thành Client Component.
Dùng cái nào khi nào?
Quyết định chọn Server hay Client Component giống như chọn món ăn: tùy vào khẩu vị (nhu cầu) của bạn. Đây là vài gợi ý:
Server Component:
- Lấy dữ liệu từ API hoặc database (fetch data ngon ơ mà không cần gửi code thừa cho client).
- Giữ logic nhạy cảm ở server (bảo mật là trên hết!).
- Chỉ hiển thị nội dung tĩnh, không cần tương tác (giảm tải JavaScript, nhanh như chớp).
Client Component:
-
- Xử lý tương tác người dùng (click nút, nhập form, đổi state).
- Dùng API của trình duyệt (như geolocation, local storage).
- Cập nhật real-time (chat, thông báo – mấy thứ “động” là phải có nó).
Kết hợp sao cho “ngọt”?
Next.js cho phép bạn mix Server Component và Client Component như một bản giao hưởng. Bí kíp là: Server Component lấy dữ liệu, Client Component xử lý tương tác. Ví dụ nhé:
Ví dụ 1: Trang Dashboard thực tế
Mình từng làm một trang dashboard hiển thị số liệu (stats) và có form cài đặt (settings). Cách mình tổ chức:
// app/dashboard/page.js (Server Component)
import Stats from './Stats';
import SettingsForm from './SettingsForm';
async function getStats() {
const res = await fetch('https://api.example.com/stats', { cache: 'no-store' });
return res.json();
}
export default async function DashboardPage() {
const stats = await getStats();
return (
< div >
< SettingsForm />
</ div >
);
);
}
// app/dashboard/Stats.js (Server Component)
export default function Stats({ stats }) {
return (
< div >
< h2 >Số liệu< /h2 >
< ul >
{stats.map(stat => (
< li key={stat.id}>{stat.name}: {stat.value}< /li >
))}
</ ul >
</ div >
);
}
// app/dashboard/SettingsForm.js (Client Component)
'use client';
import { useState } from 'react';
export default function SettingsForm() {
const [name, setName] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
await fetch('/api/settings', {
method: 'POST',
body: JSON.stringify({ name }),
});
alert('Cập nhật thành công!');
};
return (
< form onSubmit={handleSubmit} >
< input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Nhập tên mới"
/>
</ form >
);
}
DashboardPage và Stats là Server Component, lấy dữ liệu và render HTML tĩnh – nhanh và nhẹ.
SettingsForm là Client Component, xử lý form và gửi request – đúng vai trò “phục vụ” người dùng.
Hãy nghĩ Server Component như đầu bếp tài ba – nấu nướng, chuẩn bị nguyên liệu, nhưng không bao giờ ra chào khách. Còn Client Component là anh phục vụ lanh lợi – bưng bê, trò chuyện với khách, làm không khí sôi động. Đừng bắt đầu bếp đi tiếp khách, cũng đừng để phục vụ vào bếp – rối team ngay!
Kết luận
Server Component: Lấy dữ liệu, giữ bí mật, render tĩnh.
Client Component: Tương tác, dùng browser API, làm app “sống động”.
Kết hợp chúng khéo léo, bạn sẽ có một ứng dụng Next.js vừa nhanh, vừa mượt, vừa an toàn.