Server Actions là các hàm JavaScript chạy trực tiếp trên Server nhưng có thể được gọi từ Client (Form, Button, Transition).
1. Tại sao lãng phí thời gian tạo API Routes?
Trước đây:
- Tạo
app/api/post/route.ts(POST). - Viết logic xử lý.
- Ở Client dùng
fetch('/api/post', { method: 'POST', body: ... }). - Check types thủ công.
Bây giờ:
- Viết 1 function gắn
use server. - Truyền vào prop
actioncủa<form>. Xong.
2. Cách triển khai chuẩn mực
tsx:
// app/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
export async function createPost(formData: FormData) {
const title = formData.get('title');
// 1. Lưu vào Database
await db.post.create({ data: { title } });
// 2. Clear cache để Page cập nhật dữ liệu mới ngay lập tức
revalidatePath('/posts');
return { success: true };
}tsx:
// app/posts/NewPostForm.tsx
'use client';
import { createPost } from '../actions';
export function NewPostForm() {
return (
<form action={createPost}>
<input name="title" required />
<button type="submit">Đăng bài</button>
</form>
);
}3. Experience tốt hơn với useFormStatus & useActionState
Để làm UI xịn (nút Loading, hiển thị lỗi), React cung cấp các Hooks:
useFormStatus: Theo dõi trạng thái nút bấm
(Phải dùng bên trong component con của Form).
tsx:
function SubmitButton() {
const { pending } = useFormStatus();
return <button disabled={pending}>{pending ? 'Đang gửi...' : 'Gửi'}</button>;
}useActionState (React 19/Next 15): Quản lý State của Action
tsx:
const [state, formAction] = useActionState(createPost, { message: "" });
return (
<form action={formAction}>
{state.message && <p className="error">{state.message}</p>}
...
</form>
);4. Bảo mật (Security)
Server Actions mặc định là public endpoints. Đừng bao giờ tin tưởng Input từ Client:
- Luôn Validate: Dùng Zod để kiểm tra
formData. - Authentication: Kiểm tra
sessionbên trong Action. - Server-only code: Function chỉ được phép chạy trên Server.
5. Revalidation (Cập nhật UI)
Đây là điểm mạnh nhất. Sau khi Database đổi, bạn chỉ cần gọi:
revalidatePath('/'): Cập nhật route cụ thể.revalidateTag('posts'): Cập nhật theo tag (dùng trongfetch).
Kết luận
Server Actions không chỉ giúp code ngắn hơn, nó còn giúp ứng dụng progressive enhancement (vẫn chạy được khi user chưa tải xong JavaScript).
- Dùng cho mọi tác vụ ghi dữ liệu (Add, Edit, Delete).
- Kết hợp với Zod để type-safe từ Server sang Client.