Trước đây, để làm tính năng "Thêm User", bạn phải:
- Tạo file
pages/api/create-user.ts. - Ở Component, viết hàm
onSubmit->fetch('/api/create-user', { body: ... }). - Xử lý loading state, error state thủ công.
Giờ đây, bạn có thể viết hàm Backend ngay trong Component.
1. Server Action cơ bản
// app/actions.ts
'use server'; // Đánh dấu file này chỉ chạy trên Server
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db';
export async function createUser(formData: FormData) {
const name = formData.get('name');
await db.user.create({ data: { name } });
// Quan trọng: Báo cho Next.js biết data đã cũ, cần fetch lại
revalidatePath('/users');
}// app/users/page.tsx
import { createUser } from '@/app/actions';
export default function UserPage() {
return (
<form action={createUser}>
<input name="name" type="text" />
<button type="submit">Add User</button>
</form>
);
}Điều kỳ diệu: Form này hoạt động ngay cả khi User tắt JavaScript trên trình duyệt! Đây là Progressive Enhancement.
2. useActionState (Xử lý lỗi & Loading)
Trong thực tế, ta cần hiện lỗi Validation (ví dụ: "Tên ngắn quá") và Loading spinner.
React 19 cung cấp hook useActionState (trước đây là useFormState).
'use client'; // Component này phải là Client để dùng Hook
import { useActionState } from 'react';
import { createUser } from '@/app/actions'; // Action được update để trả về { message: string }
export function UserForm() {
const [state, formAction, isPending] = useActionState(createUser, { message: '' });
return (
<form action={formAction}>
<input name="name" />
{/* Disable nút khi đang gửi */}
<button disabled={isPending}>
{isPending ? 'Saving...' : 'Add User'}
</button>
{/* Hiện lỗi từ Server */}
<p className="text-red-500">{state?.message}</p>
</form>
);
}3. RevalidatePath vs RevalidateTag
Sau khi Create/Update/Delete thành công, data trên màn hình bị cũ.
revalidatePath('/users'): Xóa Cache của trang Users -> Lần tới f5 sẽ có data mới.revalidateTag('user-list'): Xóa Cache của tất cả các fetch request có gắn taguser-list(Mạnh hơn Path).
Kết luận
Server Actions giúp code gọn gàng đến khó tin (Colocation - Code xử lý nằm ngay cạnh Code UI).
Bạn không cần quản lý API URL, Content-Type, hay JSON.stringify nữa. Bạn chỉ gọi hàm JS như bình thường, Next.js lo phần RPC (Remote Procedure Call) bên dưới.