Server Actions are functions that execute on the server, callable directly from client code. Introduced in React 19 / Next.js 15.
Simple analogy: Previously to submit a form you needed to: write an API endpoint → configure fetch → handle response. Server Actions are like a "direct line" to the server: form is submitted, server processes it, result is returned.
How it works step-by-step:
"use server" at the top.<form action={...}>, the form submission triggers a server-side POST request.revalidatePath or revalidateTag).How to use:
1"use server"; // Server function marker23async function addUser(formData: FormData) {4"use server";5 const name = formData.get("name");6 await db.users.create({ data: { name } });7 revalidatePath("/users");8}910// In component:11<form action={addUser}>12 <input name="name" />13 <button type="submit">Add</button>14</form>
Server Actions vs API Routes:
Pending state with useTransition:
1function AddUserForm() {2 const [isPending, startTransition] = useTransition();34 const handleSubmit = (formData) => {5 startTransition(async () => {6 await addUser(formData);7 });8 };910 return (11 <form action={handleSubmit}>12 <input name="name" />13 <button type="submit" disabled={isPending}>14 {isPending ? "Adding..." : "Add User"}15 </button>16 </form>17 );18}
Common pitfalls:
undefined or throw.revalidatePath or revalidateTag after mutations — stale data persists.Advantages: