TRANG CHỦGIỚI THIỆUKINH NGHIỆMCÔNG NGHỆLIÊN HỆDỰ ÁNBÀI VIẾT
VIEN

Nguyễn Sinh Nhật

Software Engineer — Fullstack Developer & AI Engineer, tập trung vào web app có khả năng mở rộng và giải pháp AI thực tế.

  • Phường Ngũ Hành Sơn, Đà Nẵng, Việt Nam
  • 0328 398 467
  • nhatnguyendev251@gmail.com

Dự án

  • UCTalent
  • Unchain Labs Landing Page
  • Bridgent Viet Nam
  • UCSmile
  • Nocturne Perfume
  • Portfolio

Về trang này

  • Dự án
  • Bài viết

© 2026 Nguyễn Sinh Nhật - Portfolio

RSS
Loading blog post
Quay lại danh sách bài viết
Minh họa Next.js về cách sử dụng use client đúng cách với Server Components và Client Components.

Kiến trúc phần mềm

Một dòng use client đặt sai chỗ có thể làm Next.js nặng hơn

Hiểu ranh giới Server và Client Components trong Next.js để giảm JavaScript phía browser mà vẫn giữ trải nghiệm tương tác.

Bởi Nguyễn Sinh Nhật•Đăng ngày 02 thg 8, 2026•7 phút đọc

Mục lục

  • Sai lầm quen thuộc: biến cả page thành Client Component
  • Cách tốt hơn: tạo interactive island nhỏ
  • Khi nào thực sự cần use client?
  • Đừng biến nó thành luật cứng
  • Kết luận
Bài viết này cũng có bằng Tiếng Anh
Một dòng "use client" đặt sai chỗ có thể biến lợi thế lớn nhất của Next.js thành một React SPA nặng hơn bình thường.

Đó không có nghĩa là "use client" là xấu. Vấn đề là nhiều người dùng nó như một cách sửa nhanh khi component cần state, event handler hoặc browser API. Nếu đặt directive này ở page.tsx, layout.tsx hoặc một component cha quá lớn, bạn đang mở rộng ranh giới client nhiều hơn cần thiết.

Trong App Router, component là Server Component mặc định. Chúng có thể lấy dữ liệu ở server và dùng dependency chỉ dành cho server mà không gửi code đó xuống browser. Khi một file có "use client", file đó và các dependency được import trực tiếp bên dưới nó trở thành một phần của client-side graph.

Sai lầm quen thuộc: biến cả page thành Client Component

Một trang sản phẩm có title, dữ liệu, mô tả dài và bộ lọc tìm kiếm. Vì bộ lọc cần useState, cách dễ nhất có vẻ là biến toàn bộ page thành Client Component.

products-page.tsxtsx
"use client";

export default function ProductsPage() {
  const [query, setQuery] = useState("");

  return (
    <>
      <SearchFilters query={query} onQueryChange={setQuery} />
      <ProductGrid query={query} />
    </>
  );
}

Cách này hoạt động, nhưng page giờ đã là client boundary. Những phần vốn không cần tương tác—như layout, nội dung, formatter hoặc product grid—dễ bị kéo về phía browser hơn mức cần thiết.

Cách tốt hơn: tạo interactive island nhỏ

Giữ page và dữ liệu ở server. Chỉ tách phần thật sự cần browser thành Client Component. Bộ lọc vẫn tương tác ở browser, nhưng product grid, dữ liệu và phần nội dung còn lại vẫn được render ở server.

products-page.tsxtsx
export default async function ProductsPage({ searchParams }) {
  const products = await getProducts(searchParams.query);

  return (
    <>
      <SearchFilters />
      <ProductGrid products={products} />
    </>
  );
}
search-filters.tsxtsx
"use client";

export function SearchFilters() {
  // state, event handlers and URL interaction live here
}
server-client-boundary.mmd

Khi nào thực sự cần use client?

  • Cần useState, useEffect, onClick, onChange hoặc browser API như window và localStorage.
  • Cần query database, dùng secret, đọc file hoặc render nội dung tĩnh và dependency nặng: giữ ở Server Component.
  • Một form nhỏ, modal, dropdown hay date picker: dùng Client Component nhỏ, không nhất thiết biến cả page thành client.
Use client không đánh dấu một component có tương tác. Nó đánh dấu ranh giới nơi browser bắt đầu phải tham gia.

Đừng biến nó thành luật cứng

Dashboard realtime, rich text editor, drag-and-drop board hoặc công cụ nội bộ có client state phức tạp sẽ cần nhiều Client Component hơn. Mục tiêu không phải đưa mọi thứ về server; mục tiêu là giữ JavaScript phía client ở đúng nơi nó tạo ra giá trị.

Kết luận

Next.js mạnh không phải vì mọi thứ tự động chạy nhanh. Nó mạnh khi đội ngũ biết phần nào cần server, phần nào cần browser, và không để một interactive button kéo cả page sang client. Trước khi thêm use client, hãy hỏi: phần này có thật sự cần chạy trong browser, hay chỉ đang nằm gần một phần cần chạy trong browser?

Câu hỏi thường gặp

Không. Directive tạo ranh giới tại file được đánh dấu và dependency được import bên dưới nó. Tuy nhiên, đặt ranh giới quá cao trong cây component có thể kéo nhiều code về phía browser hơn cần thiết.

Không. Server Components không xử lý state, event handler hay browser APIs. Client Components vẫn là nơi đúng cho phần tương tác thật sự.