Next.js Server Actions

Table of Contents
Khi React lần đầu tiên tạo ra một cuộc cách mạng trong hệ sinh thái frontend, ranh giới giữa logic phía client và việc tìm nạp dữ liệu phía server là một ranh giới nghiêm ngặt. Qua nhiều năm, Next.js đã dần thu hẹp khoảng cách này—đầu tiên với getServerSideProps và getStaticProps, sau đó là với App Router và Server Components. Nhưng còn các thao tác thay đổi dữ liệu (mutations) thì sao? Làm thế nào để chúng ta gửi dữ liệu từ client trở lại server một cách liền mạch mà không gặp phải rắc rối khi xây dựng các endpoint API tùy chỉnh?
Hãy cùng tìm hiểu về Server Actions. Được giới thiệu dưới dạng tính năng alpha trong Next.js 13 và được ổn định trong Next.js 14, Server Actions đã thay đổi hoàn toàn các quy tắc về thao tác thay đổi dữ liệu full-stack trong các ứng dụng React. Trong bài phân tích chuyên sâu này, chúng ta sẽ khám phá cơ chế hoạt động của Server Actions, các vấn đề bảo mật liên quan và cách chúng tương tác với bộ nhớ đệm, cải tiến lũy tiến (progressive enhancement) và các hook nguyên thủy đang phát triển của React.
Vấn đề với các thao tác thay đổi dữ liệu truyền thống
Trước Server Actions, một biểu mẫu gửi dữ liệu điển hình trong ứng dụng React yêu cầu một dàn nhạc gồm các phần liên kết với nhau:
- Quản lý trạng thái phía client: Các input được kiểm soát bằng
useStatehoặc các thư viện biểu mẫu phức tạp nhưreact-hook-form. - API Routes: Một endpoint backend chuyên dụng (ví dụ:
/api/submit) để nhận và xử lý payload. - Logic tìm nạp: Sử dụng
fetchhoặc một thư viện tìm nạp dữ liệu (như React Query hoặc SWR) để truyền payload, xử lý trạng thái tải và phân tích phản hồi. - Xử lý lỗi: Đồng bộ hóa các lỗi xác thực phía server trở lại trạng thái phía client.
- Xác thực lại: Kích hoạt thủ công việc tìm nạp lại để đảm bảo giao diện người dùng phản ánh dữ liệu đã thay đổi.
Mặc dù có chức năng, cách tiếp cận này đã tạo ra một lượng lớn mã lặp lại (boilerplate) và các thác nước mạng (network waterfalls). Nó cũng buộc các nhà phát triển phải kết nối chặt chẽ giữa các thành phần frontend và các API route backend.
Cách Server Actions hoạt động bên dưới
Server Action, về cơ bản, là một hàm bất đồng bộ được định nghĩa trên server có thể được gọi trực tiếp từ các client hoặc server component. Khi bạn định nghĩa một hàm với chỉ thị "use server", Next.js thực hiện một bước biên dịch để thay đổi cơ bản cách hàm đó được hiển thị.
// actions.ts
"use server";
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";
export async function createPost(formData: FormData) {
const title = formData.get("title");
await db.post.create({
data: { title: title as string }
});
revalidatePath("/posts");
}
Khi bạn import và gọi hàm này từ một Client Component, Next.js không đóng gói mã của hàm vào client bundle. Thay vào đó, bundler tạo ra một cơ chế gọi thủ tục từ xa (RPC). Client bundle nhận được một hàm proxy. Khi proxy này được thực thi, nó gửi một yêu cầu HTTP POST đến server Next.js chứa định danh của action và các đối số của nó.
Server giải mã payload, thực thi hàm gốc một cách an toàn và trả về kết quả (cùng với bất kỳ cập nhật giao diện người dùng hoặc hướng dẫn xác thực lại nào). Toàn bộ quá trình này bỏ qua nhu cầu về một API route rõ ràng, giảm đáng kể mã lặp lại và gánh nặng nhận thức.
Tích hợp sâu với bộ nhớ đệm của Next.js
Một trong những khía cạnh mạnh mẽ nhất của Server Actions là sự tích hợp sâu sắc của chúng với bộ nhớ đệm của Next.js App Router. Trong các thao tác thay đổi dữ liệu REST hoặc GraphQL truyền thống, việc cập nhật dữ liệu trên server có nghĩa là bạn phải tự động vô hiệu hóa bộ nhớ đệm phía client (ví dụ: sử dụng invalidateQueries của React Query).
Với Server Actions, việc vô hiệu hóa bộ nhớ đệm được tích hợp vào framework thông qua revalidatePath và revalidateTag. Khi một action hoàn tất, Next.js có thể phản hồi bằng một lệnh cho client router để tìm nạp lại các đường dẫn cụ thể. Điều này xảy ra trong một vòng lặp mạng duy nhất.
Ví dụ:
export async function updateProfile(data: UserData) {
"use server"
await updateDb(data);
revalidateTag("user-profile");
}
Khi thực thi, Next.js sẽ tự động xóa bộ nhớ đệm phía server cho thẻ user-profile và hướng dẫn client router áp dụng payload Server Component đã cập nhật một cách liền mạch, bảo toàn trạng thái phía client nếu có thể.
Các cân nhắc về bảo mật: API vô hình
Một quan niệm sai lầm phổ biến là Server Actions là "phép thuật" và do đó không an toàn. Trên thực tế, Server Actions có chức năng giống hệt như các endpoint API công khai. Khi bạn hiển thị một Server Action, nó có thể được gọi bởi bất kỳ ai có thể thực hiện yêu cầu HTTP đến miền của bạn.
Vì lý do này, bạn phải coi mọi Server Action là một điểm vào không đáng tin cậy:
- Xác thực và ủy quyền: Bạn phải kiểm tra rõ ràng phiên và quyền của người dùng bên trong mọi action.
- Xác thực đầu vào: Không bao giờ tin tưởng
FormDatahoặc các đối số được truyền cho Server Action. Luôn sử dụng thư viện xác thực schema như Zod để làm sạch và xác thực đầu vào trước khi tương tác với cơ sở dữ liệu của bạn. - Giả mạo yêu cầu liên trang (CSRF): Next.js tự động triển khai bảo vệ CSRF cho Server Actions bằng cách thực thi kiểm tra nguồn gốc nghiêm ngặt và sử dụng các tiêu đề cụ thể, giảm thiểu một trong những lỗ hổng web phổ biến nhất.
export async function secureAction(data: unknown) {
"use server";
const session = await getSession();
if (!session) throw new Error("Unauthorized");
const parsed = mySchema.safeParse(data);
if (!parsed.success) throw new Error("Invalid input");
// Safe to proceed
}
Cải tiến lũy tiến và gửi biểu mẫu
Server Actions tỏa sáng nhất khi được sử dụng nguyên bản với các biểu mẫu HTML. Bằng cách truyền trực tiếp một Server Action vào thuộc tính action của một phần tử <form>, bạn sẽ có được cải tiến lũy tiến ngay lập tức.
import { createPost } from "./actions";
export default function PostForm() {
return (
<form action={createPost}>
<input type="text" name="title" required />
<button type="submit">Create</button>
</form>
);
}
Nếu JavaScript bị tắt hoặc không tải được, trình duyệt sẽ quay lại việc gửi biểu mẫu được mã hóa URL tiêu chuẩn. Next.js xử lý điều này một cách liền mạch, thực thi action và chuyển hướng người dùng trở lại trang đã hiển thị. Khi JavaScript được bật, React sẽ chặn việc gửi, ngăn tải lại toàn bộ trang và xử lý yêu cầu thông qua fetch, cho phép chuyển đổi mượt mà, giống như SPA.
React 19 giới thiệu các hook như useActionState và useFormStatus để xử lý trạng thái chờ và cập nhật giao diện người dùng lạc quan một cách nguyên bản. Điều này tiếp tục giảm sự phụ thuộc vào các thư viện quản lý trạng thái bên ngoài, đưa logic thay đổi dữ liệu trở lại nền tảng.
Tương lai của kiến trúc React
Next.js Server Actions đại diện cho một sự thay đổi cơ bản trong cách chúng ta kiến trúc các ứng dụng React full-stack. Bằng cách thu hẹp khoảng cách giữa client và server, giảm nhu cầu về các API route rõ ràng và tích hợp sâu sắc với các cơ chế bộ nhớ đệm, Server Actions cung cấp trải nghiệm nhà phát triển cực kỳ hiện đại nhưng vẫn dựa trên các tiêu chuẩn web cơ bản.
Mặc dù chúng yêu cầu một cách tiếp cận kỷ luật đối với bảo mật và xác thực, nhưng sự đánh đổi về năng suất và sự đơn giản là không thể phủ nhận. Khi hệ sinh thái React tiếp tục phát triển, mô hình thay đổi dữ liệu kiểu RPC được tiên phong bởi Server Actions được dự đoán sẽ trở thành tiêu chuẩn cho việc thay đổi dữ liệu trên toàn bộ framework.
Bạn cũng có thể thích
Free In-Browser Developer Tools
Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.
Related Articles

suppressHydrationWarning trong Next.js: Hướng dẫn sử dụng an toàn & gỡ lỗi đầy đủ
Hướng dẫn toàn diện về suppressHydrationWarning trong Next.js: sử dụng an toàn & gỡ lỗi đầy đủ với các ví dụ thực tế đã được kiểm chứng.
Read more
Next.js 15 Server Actions vs Route Handlers: So sánh kiến trúc chuyên sâu
Nắm vững khi nào nên chọn Server Actions so với Route Handlers trong Next.js 15, đi sâu vào progressive enhancement, hành vi caching, giao thức RPC và các ranh giới bảo mật.
Read more
Quản lý trạng thái trong React 2026: Vượt xa Redux
Hướng dẫn toàn diện về quản lý trạng thái React năm 2026: so sánh React 19 actions, trạng thái máy chủ TanStack Query, Zustand, Jotai và Signals.
Read more