Server Actions
A Server Action is a function that runs on the server, callable from your components to mutate data — no API route needed.
Syntax
'use server'; // inside an async function or at file topA Server Action is an async function marked with the "use server" directive. It runs on the server but can be called from the client, letting you mutate data (create, update, delete) without hand-writing an API endpoint or a fetch call.
How to define one
- Add
"use server"at the top of the function, or at the top of a file to export several actions. - Pass the action to a form's
actionprop, or call it from an event handler.
Example
// A form that submits directly to a Server Action
export default function NewTodo() {
async function createTodo(formData: FormData) {
'use server';
const title = formData.get('title') as string;
await db.todo.create({ data: { title } });
}
return (
<form action={createTodo}>
<input name="title" />
<button type="submit">Add</button>
</form>
);
}When to use it
- A comment form submits directly to a Server Action that saves to the database, with no API route file needed.
- A delete button invokes a Server Action to remove a record and revalidate the list — all in one function.
- A developer exposes mutation logic as a Server Action so it can be called from both a form and a button click handler.
More examples
Inline server action in a page
Placing 'use server' inside an async function makes it a Server Action that the form can call directly.
// app/items/page.tsx
export default function ItemsPage() {
async function createItem(formData: FormData) {
'use server';
const name = formData.get('name') as string;
await db.item.create({ data: { name } });
}
return (
<form action={createItem}>
<input name="name" />
<button type="submit">Add</button>
</form>
);
}Exported action in actions.ts
A top-level 'use server' directive marks every export in the file as a Server Action.
// app/actions.ts
'use server';
import { db } from '@/lib/db';
export async function deletePost(id: string) {
await db.post.delete({ where: { id } });
}Calling an action from a button
Client Components can call Server Actions as normal async functions — Next.js handles the network call.
'use client';
import { deletePost } from '@/app/actions';
export default function DeleteButton({ id }: { id: string }) {
return (
<button onClick={() => deletePost(id)}>
Delete
</button>
);
}
Discussion