A form that talks to the database
Saving a review used to mean: write an API route, call fetch from the browser, handle loading, then refresh the list. A server action is just an async function marked "use server". Pass it to a form's action and Next.js does the rest — it even works before JavaScript loads.
"use server" + <form action>
"use server";
import { revalidatePath } from "next/cache";
import { saveReview } from "@/lib/reviews";
export async function addReview(formData) {
const name = String(formData.get("name") ?? "").trim();
const text = String(formData.get("text") ?? "").trim();
if (!name || !text) return;
await saveReview(name, text);
revalidatePath("/reviews");
}- redirect("/thanks") from next/navigation after a mutation sends the user elsewhere.
- In Client Components, useActionState(action, initial) gives you the action's return value (e.g. validation errors) and a pending flag.
- Server actions are public endpoints: check the user is allowed to do what they ask.