# Server Actions trong Next.js 16 (2026): Mutation, Revalidation và câu hỏi phỏng vấn > Cách Server Actions trong Next.js 16 xử lý mutation, revalidation, trạng thái đang chờ, giao diện lạc quan và bảo mật, kèm những câu hỏi phỏng vấn kiểm tra từng khái niệm. - Published: 2026-06-24 - Updated: 2026-07-06 - Author: SharpSkill - Tags: next.js, server-actions, react, mutations, revalidation, interview - Reading time: 11 min --- Server Actions của Next.js biến một hàm async thông thường thành một endpoint xử lý mutation phía máy chủ mà form có thể gọi trực tiếp, không cần API route, không cần `fetch` phía client, và không cần tự tay serialize JSON. Trong Next.js 16, đây là cách mặc định để viết các thao tác thay đổi dữ liệu, và chúng xuất hiện trong hầu hết mọi buổi phỏng vấn React cấp senior năm 2026. Bài phân tích chuyên sâu này mổ xẻ cách chúng thực thi, cách quá trình revalidation truyền dữ liệu mới tới giao diện, cách mô hình hóa trạng thái đang chờ và lỗi, cùng những quy tắc bảo mật khiến phần lớn lập trình viên vấp phải. > **Định nghĩa trong một câu** > > Server Action là một hàm async được đánh dấu bằng `"use server"`, chỉ chạy trên máy chủ và có thể được gọi từ một client component hoặc một form như thể nó là hàm cục bộ, trong khi Next.js tự động xử lý request mạng, việc serialize tham số, và bảo vệ CSRF. ## Cách Server Actions thực thi bên dưới lớp vỏ Một Server Action là một hàm chỉ chạy trên máy chủ, được gọi qua mạng thông qua một endpoint do trình biên dịch sinh ra. Khi một hàm mang chỉ thị `"use server"`, trình biên dịch của Next.js không bao giờ gửi phần thân hàm xuống trình duyệt. Thay vào đó, nó thay thế hàm bằng một tham chiếu nhẹ: một action ID đã băm được ánh xạ tới một route POST được sinh tự động. Khi gọi action từ client, một request sẽ được gửi tới route đó, hàm thật chạy trên máy chủ, và kết quả đã được serialize sẽ được stream ngược lại phía gọi. Thiết kế này kéo theo ba hệ quả đáng ghi nhớ cho cả code sản xuất lẫn phỏng vấn. Thứ nhất, tham số và giá trị trả về phải serialize được, vì chúng vượt qua mạng dưới dạng payload đã mã hóa. Thứ hai, các bí mật vẫn nằm trên máy chủ, bởi phần thân hàm không bao giờ được đóng gói cho client. Thứ ba, các action gắn vào một `
` vẫn hoạt động ngay cả trước khi hydrate, đó là lý do progressive enhancement là một điểm bán hàng cốt lõi. [Hướng dẫn cập nhật dữ liệu của Next.js](https://nextjs.org/docs/app/getting-started/updating-data) mô tả đầy đủ mô hình thực thi này. Mọi Server Action đều nằm trong một tệp hoặc một khối được đánh dấu `"use server"`. Một mutation đơn giản trông như sau: ```typescript // app/posts/actions.ts "use server" import { revalidatePath } from "next/cache" import { redirect } from "next/navigation" import { PostService } from "@/lib/services/post-service" export async function createPost(formData: FormData) { // FormData values arrive as strings; cast explicitly const title = formData.get("title") as string const body = formData.get("body") as string // Run business logic through the service layer, never the ORM directly const post = await PostService.create({ title, body }) // Purge the cached list so the next request refetches it revalidatePath("/posts") // Send the user to the freshly created resource redirect(`/posts/${post.id}`) } ``` Hàm đọc `FormData` đã gửi lên, lưu dữ liệu thông qua một service, vô hiệu hóa cache của danh sách, rồi chuyển hướng. Không cần bất kỳ JavaScript phía client nào cho toàn bộ quá trình này. ## Kết nối Server Action với form mà không cần JavaScript phía client Truyền action vào prop `action` của form là cách tích hợp đơn giản nhất. Next.js serialize dữ liệu gửi đi thành `FormData` và gọi hàm trên máy chủ. Vì cách này sử dụng cơ chế submit form gốc của trình duyệt, nó vẫn hoạt động khi JavaScript bị tắt và nâng cấp mượt mà ngay khi trang được hydrate. ```tsx // app/posts/new-post-form.tsx import { createPost } from "./actions" export default function NewPostForm() { return (