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 top

A 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.

A form submits to a Server Action which mutates data and refreshes the page <form action= {createTodo}> Server Action "use server" write to DB revalidatePath fresh UI sent 1. user submits (no client JS required) 2. server runs the action securely 3. cache is revalidated, page updates in place
Server Actions let a form mutate data on the server and refresh the UI without writing an API route.

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 action prop, or call it from an event handler.

Example

Example · typescript
// 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.

Example · ts
// 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.

Example · ts
// 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.

Example · ts
'use client';
import { deletePost } from '@/app/actions';

export default function DeleteButton({ id }: { id: string }) {
  return (
    <button onClick={() => deletePost(id)}>
      Delete
    </button>
  );
}

Discussion

  • Be the first to comment on this lesson.