React Server Components (RSC) đã thay đổi căn bản cách chúng ta xây dựng ứng dụng React. Bằng cách chuyển logic render sang server, chúng ta có thể giảm đáng kể JavaScript bundle gửi tới client, dẫn đến thời gian tải nhanh hơn và trải nghiệm người dùng tốt hơn. Trong bài viết này, chúng ta sẽ khám phá các pattern nâng cao và best practices để tận dụng RSC trong năm 2026.
Server Components là gì?
Theo truyền thống, các component React được render hoàn toàn trên client (CSR) hoặc pre-render trên server dưới dạng HTML (SSR) rồi hydrate trên client. Server Components cho phép chúng ta render component chỉ trên server. Code của chúng không bao giờ được gửi tới trình duyệt.
Lợi ích
- Kích thước Bundle bằng không: Các dependency được sử dụng trong Server Components (như markdown parser hay thư viện date nặng) ở lại trên server.
- Truy cập trực tiếp Backend: Bạn có thể truy vấn database trực tiếp bên trong component mà không cần expose API endpoint.
- Code Splitting tự động: Client components được import từ phía server sẽ tự động được code-split.
Pattern lấy dữ liệu
Với RSC, bạn có thể làm component async và await dữ liệu trực tiếp.
// app/users/page.tsx import { db } from '@/lib/db'; export default async function UsersPage() { const users = await db.user.findMany(); return ( <main> <h1>Users</h1> <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> </main> ); }
Suspense cho Streaming
Vì việc lấy dữ liệu có thể chậm, hãy bọc component trong <Suspense> để hiển thị fallback UI ngay lập tức trong khi dữ liệu đang tải.
import { Suspense } from 'react'; import UserList from './UserList'; import LoadingSkeleton from './LoadingSkeleton'; export default function Page() { return ( <section> <h1>My Users</h1> <Suspense fallback={<LoadingSkeleton />}> <UserList /> </Suspense> </section> ); }
Kết hợp Server và Client Components
Một trong những khía cạnh gây nhầm lẫn nhất là cách kết hợp Server và Client components.
Quy tắc chung: Server Components có thể import Client Components. Client Components không thể import Server Components trực tiếp. Tuy nhiên, bạn có thể truyền Server Component như children cho Client Component.
Pattern "Children"
// ClientComponent.tsx 'use client'; import { useState } from 'react'; export default function ClientWrapper({ children }) { const [count, setCount] = useState(0); return ( <div onClick={() => setCount((c) => c + 1)}> Count: {count} {children} {/* This can be a Server Component! */} </div> ); }
// ServerPage.tsx import ClientWrapper from './ClientWrapper'; import ServerContent from './ServerContent'; export default function Page() { return ( <ClientWrapper> <ServerContent /> {/* This works perfectly */} </ClientWrapper> ); }
Những cạm bẫy thường gặp
- Sử dụng Context trong Server Components: Context là khái niệm phía client. Nếu bạn cần chia sẻ dữ liệu phía server, hãy truyền qua props hoặc sử dụng cache phạm vi request chuyên biệt.
- Thêm Event Handlers: Bạn không thể thêm
onClickhayonChangevào Server Component. Logic đó thuộc về Client Component node lá chung.
Kết luận
React Server Components không chỉ là một tính năng; đây là sự thay đổi mô hình. Bằng cách hiểu ranh giới giữa server và client, bạn có thể xây dựng ứng dụng vừa có tính tương tác cao vừa nhanh đáng kinh ngạc.