The Wide Point
Web Dev Jun 10, 2025 6 min read TheWidePoint Team

Next.js Server Actions: The Complete Guide for 2025

Server Actions changed how we think about mutations in React. Here's everything you need to know to use them confidently.

Server Actions are one of the most exciting additions to Next.js. They let you write server-side code directly inside your components — no API routes needed for simple mutations.

What Are Server Actions?

A Server Action is an async function that runs on the server but can be called from the client. Next.js handles the serialisation, CSRF protection, and network layer automatically.

// app/actions.ts
"use server";

export async function createPost(formData: FormData) {
  const title = formData.get("title") as string;
  await db.posts.create({ data: { title } });
  revalidatePath("/blog");
}

Using Them in Forms

The cleanest pattern — pass the action directly to a <form>:

import { createPost } from "./actions";

export default function NewPostForm() {
  return (
    <form action={createPost}>
      <input name="title" placeholder="Post title" />
      <button type="submit">Create</button>
    </form>
  );
}

Progressive Enhancement

This works even with JavaScript disabled. The form falls back to a standard HTML form submission, and Next.js handles the rest. This is real progressive enhancement, not a polyfill.

Handling Errors and Loading State

Use useActionState (previously useFormState) to handle responses:

"use client";

import { useActionState } from "react";
import { createPost } from "./actions";

export default function NewPostForm() {
  const [state, action, isPending] = useActionState(createPost, null);

  return (
    <form action={action}>
      <input name="title" />
      {state?.error && <p className="text-red-500">{state.error}</p>}
      <button disabled={isPending}>
        {isPending ? "Creating..." : "Create Post"}
      </button>
    </form>
  );
}

When Not to Use Server Actions

  • For read operations — use fetch or server components directly
  • For complex multi-step flows — a traditional API route is clearer
  • When you need streaming responses — use Route Handlers

Conclusion

Server Actions are the right tool for mutations that don't need a dedicated API. They simplify your codebase, improve security, and enable progressive enhancement out of the box.