Tấn Phát Digital

React Server Actions Generator

Tạo Next.js Server Actions với validation và error handling

Settings
Generated Code

Hợp tác ngay với Tấn Phát Digital

Chúng tôi không chỉ thiết kế website, mà còn giúp doanh nghiệp xây dựng thương hiệu số mạnh mẽ. Cung cấp dịch vụ thiết kế website trọn gói từ thiết kế đến tối ưu SEO. Hãy liên hệ ngay với Tấn Phát Digital để cùng tạo nên những giải pháp công nghệ đột phá, hiệu quả và bền vững cho doanh nghiệp của bạn tại Hồ Chí Minh.

Sinh khung Server Action cho Next.js App Router: 'use server', Zod, revalidatePath và useActionState

React Server Actions Generator của Tấn Phát Digital sinh một file Server Action TypeScript làm điểm khởi đầu cho form trong Next.js App Router với React 19. Bạn đặt tên action, bật hoặc tắt Zod validation và revalidatePath; công cụ tạo file có chỉ thị 'use server', kiểu ActionState dùng chung, hàm async với chữ ký (prevState, formData) đúng với hook useActionState, bước validate phía server trả về lỗi theo từng field, khối try/catch không lộ lỗi nội bộ, lời nhắc kiểm tra đăng nhập và quyền, cùng ví dụ Client Component dùng useActionState trong phần chú thích. Đây là bộ khung để bạn điền schema và logic thật, không phải trình sinh CRUD hay tích hợp ORM.

Tính năng nổi bật

  • Sinh file Server Action TypeScript có chỉ thị 'use server' ở đầu file
  • Tên action tùy chọn, kiểm tra là định danh JavaScript hợp lệ trước khi sinh code
  • Chữ ký (prevState, formData) và kiểu trả về Promise<ActionState> dùng thẳng được với useActionState của React 19
  • Tùy chọn Zod validation: schema mẫu, safeParse trên server, trả fieldErrors theo từng field
  • Tùy chọn revalidatePath từ next/cache, chỉ chạy khi thao tác thành công
  • Khối try/catch ghi log lỗi ở server và trả thông báo chung, không lộ chi tiết nội bộ cho client
  • Chú thích nhắc kiểm tra đăng nhập và quyền vì Server Action là endpoint POST công khai
  • Kèm ví dụ Client Component dùng useActionState, hiển thị lỗi field, trạng thái isPending
  • Code sinh ra đã được kiểm tra kiểu với TypeScript strict, React 19 và Zod 3
  • Copy toàn bộ code bằng một nút, miễn phí

Server Actions thay thế API Routes như thế nào?

Trước khi có Server Actions, mọi thao tác ghi dữ liệu từ form phải đi qua API route (ví dụ /api/users) với khá nhiều code lặp: tạo route, gọi fetch() từ client, tự quản lý trạng thái loading và lỗi, parse JSON, validate request rồi trả JSON về. Server Actions trong Next.js App Router đơn giản hóa việc này: bạn viết một hàm async chạy trên server, đánh dấu 'use server', rồi gắn thẳng vào thuộc tính action của form hoặc gọi từ client như một hàm bình thường. Lợi ích: kiểu dữ liệu được TypeScript theo dõi từ đầu đến cuối mà không cần viết hợp đồng API riêng; form có thể gửi được cả khi JavaScript chưa tải xong (progressive enhancement); Next.js tự tạo endpoint, không cần cấu hình; tích hợp với transitions, useActionState, useOptimistic của React; logic nằm ở server nên không làm tăng bundle phía client; và làm mới dữ liệu đã cache ngay sau thao tác bằng revalidatePath hoặc revalidateTag. Dù vậy, Server Action vẫn là một endpoint HTTP, nên các nguyên tắc bảo mật của API vẫn áp dụng đầy đủ.

Lợi ích khi sử dụng

  • Bớt nhiều code lặp so với API route cho các thao tác ghi dữ liệu nội bộ
  • Type-safe từ server tới client mà không cần OpenAPI hay tRPC
  • Progressive enhancement: form gắn trực tiếp Server Action có thể gửi được khi JavaScript chưa tải xong
  • Làm mới cache ngay sau thao tác bằng revalidatePath hoặc revalidateTag
  • Giảm bundle phía client vì logic chạy trên server
  • Truy cập trực tiếp database hoặc dịch vụ nội bộ, không cần lớp REST trung gian
  • Tích hợp tự nhiên với transitions, useActionState và useOptimistic
  • Khung code sinh sẵn đã có validate phía server và nhắc kiểm tra quyền

Hướng dẫn tạo và sử dụng Server Actions

  1. 1Nhập tên action vào ô Action Name, ví dụ createUser hoặc updateProfile. Tên phải bắt đầu bằng chữ cái, _ hoặc $ và không có khoảng trắng.
  2. 2Bật Include Zod Validation nếu muốn có schema và bước validate phía server (cần cài gói zod trong dự án).
  3. 3Bật Include Revalidation nếu sau khi lưu cần làm mới dữ liệu đang hiển thị ở một đường dẫn.
  4. 4Bấm Generate Server Action để sinh code, rồi bấm nút copy.
  5. 5Dán vào một file riêng, ví dụ app/actions.ts, thay schema mẫu bằng các field thật của form và thêm logic ghi dữ liệu vào khối try.
  6. 6Thêm kiểm tra đăng nhập và quyền ở đầu hàm, đổi đường dẫn trong revalidatePath thành trang đang hiển thị dữ liệu.
  7. 7Tạo Client Component theo ví dụ trong phần chú thích cuối file: dùng useActionState, gắn formAction vào form và hiển thị state.message, state.fieldErrors.
  8. 8Chạy npm run dev, gửi form với dữ liệu hợp lệ và không hợp lệ để kiểm tra cả hai nhánh.

Pattern chuẩn cho Server Actions với validation và error handling

Cấu trúc nên theo: 1) Đánh dấu 'use server' ở đầu file (hoặc đầu thân hàm nếu hàm nằm trong Server Component). 2) Định nghĩa Zod schema cho input. 3) Kiểm tra đăng nhập và quyền ngay đầu hàm. 4) Validate input bằng schema.safeParse(), không ném lỗi mà trả về lỗi theo field. 5) Thực hiện logic nghiệp vụ, ví dụ ghi database, trong try/catch. 6) Gọi revalidatePath() hoặc revalidateTag() để làm mới cache. 7) Trả về một object có hình dạng cố định như { success, message, fieldErrors } cho các lỗi dự đoán được; chỉ để lỗi ngoài dự kiến rơi vào error boundary. 8) Tùy chọn gọi redirect() để chuyển trang, lưu ý redirect hoạt động bằng cách ném ra một lỗi đặc biệt nên phải gọi ngoài khối try/catch. Phía client: useActionState để giữ kết quả và trạng thái đang gửi, useFormStatus cho nút bấm nằm trong form, useOptimistic để cập nhật giao diện ngay. Cần xử lý đủ ba nhánh: lỗi validate, lỗi quyền và lỗi server, mỗi nhánh có thông báo rõ ràng.

Code công cụ sinh ra gồm những gì, giải thích từng phần

Với tên createUser và bật cả hai tùy chọn, file sinh ra có: dòng 'use server'; import z từ zod và revalidatePath từ next/cache; kiểu ActionState gồm success, message và fieldErrors; schema mẫu với một field name bắt buộc sau khi cắt khoảng trắng; hàm export async function createUser(prevState: ActionState, formData: FormData): Promise<ActionState>. Trong hàm là chú thích nhắc kiểm tra quyền, rồi schema.safeParse({ name: formData.get('name') }); nếu thất bại trả về success: false kèm validatedFields.error.flatten().fieldErrors, nếu thành công đi tiếp vào try, nơi bạn gọi database với validatedFields.data. Lỗi trong try được console.error ở server và client chỉ nhận thông báo chung. revalidatePath('/') chỉ chạy khi không có lỗi, sau đó trả về success: true. Cuối file là một khối chú thích chứa Client Component mẫu. Chúng tôi đã kiểm tra cả bốn tổ hợp bật tắt tùy chọn bằng TypeScript ở chế độ strict với React 19 và Zod 3, không có lỗi kiểu.

useActionState thay cho useFormState: thay đổi của React 19

Trong React 19, hook useFormState của react-dom được đổi tên và chuyển thành useActionState, import từ react. Chữ ký là const [state, formAction, isPending] = useActionState(action, initialState): hook trả thêm isPending nên không cần useFormStatus chỉ để biết form đang gửi. Action truyền vào nhận hai tham số (prevState, formData) chứ không phải chỉ formData, đây là lý do code sinh ra có tham số prevState dù thân hàm chưa dùng tới. Next.js 15 dùng React 19 cho App Router, nên với dự án mới hãy dùng useActionState. Nếu dự án còn ở Next.js 14 với React 18, useActionState chưa có; khi đó dùng useFormState từ react-dom với cùng chữ ký (prevState, formData), phần Server Action giữ nguyên.

Lỗi kiểu thường gặp: gắn action trả về object thẳng vào form

Một lỗi rất phổ biến khi nâng lên React 19 là viết action dạng async function createUser(formData: FormData) trả về { error: '...' } rồi gắn thẳng <form action={createUser}>. Với kiểu dữ liệu của React 19, thuộc tính action của form chỉ nhận hàm trả về void hoặc Promise<void>, nên TypeScript báo lỗi kiểu không gán được, và kể cả khi bỏ qua lỗi thì giá trị trả về cũng bị bỏ đi, người dùng không bao giờ thấy thông báo lỗi. Có hai cách đúng: action không cần báo kết quả thì trả về void (có thể redirect sau khi xong); action cần báo lỗi hoặc thành công thì dùng chữ ký (prevState, formData) và gắn qua useActionState như code công cụ sinh ra.

Bảo mật Server Actions: những điều khung code không tự làm thay bạn

Mỗi Server Action được export sẽ trở thành một endpoint POST mà bất kỳ ai cũng có thể gọi trực tiếp, không cần đi qua giao diện của bạn. Vì vậy: luôn kiểm tra phiên đăng nhập và quyền trên từng action, không dựa vào việc nút bấm bị ẩn ở giao diện; luôn validate lại input trên server dù client đã kiểm tra; không nhận các trường nhạy cảm như userId, role, giá tiền từ formData khi server tự xác định được; không trả lỗi gốc từ database về client. Next.js có một số lớp bảo vệ mặc định: so sánh header Origin với Host để giảm nguy cơ CSRF, tạo ID khó đoán cho action và loại bỏ action không được dùng khỏi bản build, giới hạn kích thước body mặc định 1MB (chỉnh bằng serverActions.bodySizeLimit). Các lớp này không thay thế được kiểm tra quyền. Với thao tác dễ bị lạm dụng như gửi form liên hệ, đăng ký, hãy thêm giới hạn tần suất theo IP hoặc tài khoản.

Server Actions vs API Routes vs tRPC: khi nào dùng cái nào

Server Actions: phù hợp nhất cho thao tác ghi dữ liệu từ chính ứng dụng Next.js như gửi form, bấm nút. Type-safe, ít code lặp, hỗ trợ progressive enhancement. Route Handlers (API Routes): cần khi có client bên ngoài (ứng dụng di động, bên thứ ba), webhook, API công khai có quản lý phiên bản và giới hạn tần suất, hoặc khi cần trả luồng dữ liệu, file, định dạng tùy ý. Server Action cũng không phù hợp để đọc dữ liệu: chúng chạy tuần tự và dùng phương thức POST, việc đọc dữ liệu nên làm trong Server Component hoặc route handler. tRPC: phù hợp khi cần type-safety nhưng dùng backend riêng như Express, Hono, hoặc nhiều loại client. Mô hình kết hợp thường gặp: Server Actions cho thao tác nội bộ, Route Handlers cho endpoint công khai và webhook. Có thể chuyển dần từ API route sang Server Actions, giữ API route cũ cho client bên ngoài.

Zod 3 và Zod 4: lưu ý khi dùng code sinh ra

Code sinh ra dùng z.object, z.string().trim().min() và safeParse, các API này giống nhau ở Zod 3 và Zod 4. Phần khác biệt là cách gom lỗi theo field: validatedFields.error.flatten().fieldErrors là cách chuẩn ở Zod 3; ở Zod 4 phương thức này vẫn chạy nhưng đã bị đánh dấu không khuyến khích, cách mới là z.flattenError(validatedFields.error).fieldErrors. Kiểm tra phiên bản zod trong package.json của bạn. Lưu ý thêm: formData.get() trả về string, File hoặc null. Nếu input không có trong form, giá trị là null và Zod sẽ báo lỗi kiểu thay vì thông báo bạn đặt trong min(); với checkbox, trường chưa tích cũng là null, nên dùng z.coerce hoặc xử lý riêng; với số, dùng z.coerce.number() vì dữ liệu form luôn là chuỗi.

Giới hạn của công cụ

Công cụ chỉ có ba thiết lập: tên action, bật tắt Zod và bật tắt revalidatePath. Nó không sinh CRUD theo entity, không tích hợp Prisma hay Drizzle, không sinh code upload file, useOptimistic, redirect, cookies hay rate limiting, và không tự thêm thư viện xác thực như Auth.js hay Clerk; phần kiểm tra quyền chỉ là chú thích để bạn tự viết. Schema chỉ có một field mẫu name, đường dẫn revalidate mặc định là trang chủ, và ví dụ Client Component nằm trong khối chú thích để bạn tách ra file riêng có 'use client'. Hãy xem đầu ra là bộ khung đúng chuẩn để bắt đầu, sau đó đọc tài liệu Next.js và React cho phiên bản bạn đang dùng.

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

Server Actions hoạt động như thế nào bên dưới?

Khi gọi Server Action từ client, Next.js gửi một POST request tới chính URL của trang, kèm header Next-Action chứa ID của action. Server tìm đúng hàm theo ID, chạy trên server rồi trả kết quả đã tuần tự hóa qua giao thức của React Server Components; phía client, React cập nhật state và có thể nhận luôn giao diện đã render lại. ID của action được tạo khó đoán và action không dùng tới bị loại khỏi bản build, nhưng ID không phải cơ chế bảo mật: ai biết ID vẫn gọi được, nên mỗi action phải tự kiểm tra quyền.

Server Actions có thay thế hoàn toàn API Routes không?

Với thao tác ghi dữ liệu trong nội bộ ứng dụng Next.js, phần lớn trường hợp có. Với client bên ngoài (ứng dụng di động, dịch vụ bên thứ ba), webhook, API công khai hoặc trả file và luồng dữ liệu, vẫn cần Route Handlers. Thực tế tốt: Server Actions cho thao tác từ giao diện, Route Handlers cho tích hợp. Hai cách dùng song song trong cùng dự án được, và có thể chuyển dần: action mới dùng Server Actions, giữ API route cũ.

Làm sao validate input trong Server Actions?

Cách phổ biến là dùng Zod: khai báo schema như z.object({ name: z.string().min(1), age: z.coerce.number().int() }), rồi gọi schema.safeParse() với dữ liệu lấy từ formData; nếu success là false thì trả về lỗi theo field thay vì ném lỗi. Zod suy ra kiểu nên TypeScript biết hình dạng dữ liệu sau khi validate. Có thể dùng Valibot (nhẹ hơn), Yup hoặc tự viết. Quan trọng nhất: LUÔN validate trên server, kể cả khi client đã validate, vì không thể tin dữ liệu từ client.

useActionState (trước đây là useFormState) và useOptimistic dùng khi nào?

useActionState giữ kết quả của action (thành công, lỗi, dữ liệu) qua các lần render và cho biết action đang chạy: const [state, formAction, isPending] = useActionState(action, initialState). Dùng cho form cần hiện lỗi validate, thông báo thành công. Trong React 19 nó thay cho useFormState của react-dom. useOptimistic cập nhật giao diện ngay trước khi server trả lời: const [optimisticTodos, addOptimistic] = useOptimistic(todos, reducer). Dùng khi muốn trải nghiệm thật mượt như bấm thích, thêm việc cần làm, bình luận: giao diện đổi ngay, rồi đồng bộ với kết quả thật từ server.

Server Actions có thể gọi từ Client Component không?

Có. Import action từ file có 'use server' vào Client Component rồi gọi như hàm async: await myAction(data); hoặc gắn qua thuộc tính action của form; hoặc qua useActionState. Lưu ý không thể khai báo Server Action ngay trong file Client Component; action phải nằm trong file 'use server' riêng, hoặc được khai báo trong Server Component rồi truyền xuống qua props. TypeScript theo dõi đúng kiểu tham số và kiểu trả về.

Làm sao test Server Actions?

Unit test như một hàm async bình thường: import action, mock các phụ thuộc (database, hàm lấy phiên đăng nhập), gọi action với FormData giả rồi kiểm tra kết quả; chỉ thị 'use server' chỉ là một chuỗi nên không cần xử lý đặc biệt. Các hàm như revalidatePath, redirect, cookies cần ngữ cảnh request của Next.js, nên hãy mock module next/cache và next/navigation trong unit test. Kiểm tra hành vi thật như làm mới cache hay chuyển trang bằng test end-to-end với Playwright: mở trang, điền form, gửi và kiểm tra giao diện.

Vì sao code sinh ra có tham số prevState dù không dùng tới?

Vì useActionState luôn gọi action với hai tham số: state trước đó và FormData. Nếu hàm chỉ khai báo formData, tham số đầu tiên sẽ nhận nhầm state và formData.get sẽ lỗi. Giữ prevState ở vị trí đầu là bắt buộc; bạn có thể dùng nó để, ví dụ, giữ lại giá trị cũ hoặc đếm số lần gửi.

revalidatePath nên đặt ở đâu và truyền đường dẫn nào?

Gọi sau khi thao tác ghi dữ liệu đã thành công, không gọi khi validate thất bại hay có lỗi, như code sinh ra đang làm. Truyền đường dẫn của trang đang hiển thị dữ liệu vừa đổi, ví dụ revalidatePath('/admin/users'); với route động có thể dùng revalidatePath('/blog/[slug]', 'page'). Nếu dữ liệu được fetch với tag, dùng revalidateTag để làm mới đúng những chỗ dùng tag đó.

Có cần kiểm tra đăng nhập trong mỗi Server Action không?

Có. Mỗi Server Action được export là một endpoint có thể bị gọi trực tiếp mà không qua giao diện, và middleware hay layout kiểm tra đăng nhập không tự bảo vệ action. Hãy lấy phiên đăng nhập ở đầu hàm, kiểm tra quyền trên đúng bản ghi sắp sửa, và lấy userId từ phiên chứ không nhận từ formData.

Gọi redirect() trong Server Action có cần lưu ý gì?

redirect() của next/navigation hoạt động bằng cách ném ra một lỗi đặc biệt để Next.js bắt và chuyển trang. Nếu gọi nó bên trong try/catch, catch sẽ nuốt mất lỗi này và trang không chuyển. Hãy gọi redirect() sau khối try/catch, và gọi revalidatePath trước redirect nếu cần làm mới dữ liệu.

Server Action có giới hạn dung lượng dữ liệu gửi lên không?

Có. Mặc định Next.js giới hạn body của Server Action ở 1MB để tránh lạm dụng. Nếu form có upload file lớn hơn, cấu hình serverActions.bodySizeLimit trong next.config (vị trí cấu hình khác nhau giữa các phiên bản Next.js), hoặc cân nhắc upload trực tiếp lên dịch vụ lưu trữ bằng URL ký sẵn thay vì đi qua Server Action.

Code sinh ra dùng được với Next.js 14 không?

File Server Action dùng được với Next.js 14 App Router. Riêng ví dụ Client Component dùng useActionState của React 19; với Next.js 14 chạy React 18, hãy đổi thành useFormState import từ react-dom. Hook này trả về [state, formAction] và không có isPending, nên dùng useFormStatus trong nút bấm nếu cần trạng thái đang gửi.

Có nên dùng Server Action để lấy dữ liệu (đọc) không?

Không nên. Server Action được thiết kế cho thao tác ghi dữ liệu: dùng phương thức POST, không được cache như fetch thông thường và các lời gọi từ client được xếp hàng chạy tuần tự. Để đọc dữ liệu, hãy fetch trong Server Component, hoặc dùng Route Handler nếu client cần gọi.

Tên action có được đặt bằng tiếng Việt có dấu không?

Công cụ chỉ chấp nhận tên bắt đầu bằng chữ cái Latin, _ hoặc $, tiếp theo là chữ, số, _ hoặc $, ví dụ taoNguoiDung. Về lý thuyết JavaScript cho phép một số ký tự Unicode trong tên hàm, nhưng tên có dấu gây khó cho việc tìm kiếm, gõ phím và công cụ lint, nên công cụ cố ý không cho phép.

Nếu tắt Zod validation thì code có còn an toàn không?

Khung code vẫn chạy nhưng không còn bước kiểm tra dữ liệu, nên bạn phải tự validate trước khi ghi database: kiểm tra kiểu, độ dài, định dạng, giá trị cho phép. Chỉ nên tắt khi action không nhận input từ người dùng, hoặc khi dự án đã có lớp validate riêng như Valibot.

Từ khóa liên quan

  • react server actions generator
  • next.js server actions
  • server actions next.js 15
  • server actions zod validation
  • useActionState
  • useActionState react 19
  • useFormState deprecated
  • useOptimistic
  • next.js form action
  • react 19 server actions
  • next.js revalidatePath
  • use server
  • server actions bảo mật
  • type-safe server functions
  • next.js app router form
  • zod safeParse formData
  • next.js mutations tutorial
  • server actions vs api routes

Công cụ Developer Tools liên quan

.env Generator

Tạo file .env và .env.example cho dự án.

.gitignore Generator

Tạo .gitignore cho Node.js, Python, Java.

API Mock Generator

Tạo mock JSON data cho API testing.

API Response Formatter

Format và phân tích API response.

API Tester

Test REST API: GET, POST, PUT, DELETE.

Postman Alternative - API Testing Tool Online với Collections, Environment & File Upload

Postman Alternative miễn phí - Test APIs với Collections, Multiple Environments, Pre-request Scripts, Collection Runner, File Upload (form-data), Tests/Assertions, Code Generation (cURL, JS, Python, Node.js). Browser-based, không cần cài đặt. Save requests, export/import collections, auto-save history. Hỗ trợ Bearer Token, Basic Auth, API Key. Hoàn hảo cho API development và testing.

Swagger API Tester - Test API với OpenAPI/Swagger Spec & Authentication Online

Swagger API Tester miễn phí - Import OpenAPI/Swagger specification và test API endpoints với đầy đủ authentication (Bearer Token/JWT, Basic Auth, API Key). Hỗ trợ OpenAPI 3.0, Swagger 2.0, auto-parse endpoints, parameters, request body. Giao diện như Swagger UI với color-coded methods, grouped endpoints, real-time testing. Hoàn hảo cho API development, testing, debugging secured APIs.

Base Converter

Chuyển đổi Binary, Hex, Base32.

Base64 Encoder

Mã hóa/giải mã Base64.

Binary Converter

Chuyển đổi Decimal, Binary, Hex.

Box Shadow Generator

Tạo CSS box-shadow trực quan.

Chmod Calculator

Tính quyền file Linux.

Dịch vụ của Tấn Phát Digital

Đang xây sản phẩm và cần thêm người làm phần nặng?

Gói giải pháp doanh nghiệp

Nền tảng custom cho ngân hàng, y tế và sàn B2B, chuẩn ISO 27001, GDPR, PCI-DSS, SLA 99.99%.

Từ 50.000.000đXem chi tiết →

Dịch vụ phát triển Blockchain & Web3

Smart contract, dApp và NFT marketplace đa chuỗi, audit bảo mật đầy đủ trước khi lên mainnet.

Từ 50.000.000đXem chi tiết →

Dịch vụ thiết kế website tại Hồ Chí Minh

Website doanh nghiệp, bán hàng và đặt lịch, chuẩn SEO ngay từ cấu trúc, tốc độ tải dưới 3 giây.

Từ 5.000.000đXem chi tiết →

Dịch vụ thiết kế landing page

Trang đích riêng cho từng chiến dịch quảng cáo, tỷ lệ chuyển đổi 3–8%, bàn giao trong 5–21 ngày.

Từ 3.000.000đXem chi tiết →

Tư vấn và báo giá miễn phí trong 24 giờ. Xem toàn bộ dịch vụ

TAN PHATDIGITAL