JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsnextjsServer Actions
Prev
nextjs
advanced
11 min read

Server Actions

forms
mutations
nextjs
progressive-enhancement
react
revalidation
server-actions
useActionState
useOptimistic

Server Actions are async functions marked with 'use server' that run exclusively on the server — they replace API routes for mutations (form submissions, data updates), support progressive enhancement (forms work without JavaScript), and integrate with React's useActionState and useOptimistic for pending/optimistic UI.

Key Points

1'use server' Functions

Async functions that run exclusively on the server — code never ships to the client. Called from forms via action prop or from event handlers.

2Progressive Enhancement

Forms using Server Actions work with JavaScript disabled (standard POST submit). With JS enabled, submission is seamless without full page reload.

3React Integration

useActionState provides pending state and form results. useOptimistic shows expected results immediately while the server processes.

4Security and Revalidation

Server-only code, but always validate inputs (they're POST endpoints). Revalidate cached data after mutations with revalidatePath/revalidateTag.

What You'll Learn

  • Create Server Actions for form submissions and data mutations
  • Implement pending states with useActionState and optimistic updates with useOptimistic
  • Understand progressive enhancement and why Server Actions work without JavaScript
  • Know the security considerations for Server Actions (input validation, authentication)

Deep Dive

Server Actions are the App Router's mechanism for handling data mutations — form submissions, database writes, and any operation that changes data. They replace the pattern of creating API routes and calling them with fetch.

What Server Actions Are

A Server Action is an async function marked with 'use server' that runs exclusively on the server:

TypeScript
// In a Server Component or separate file
async function createPost(formData: FormData) {
  'use server';
  const title = formData.get('title') as string;
  const content = formData.get('content') as string;
  await db.posts.create({ data: { title, content } });
  revalidatePath('/posts');
}

When called from the client, Next.js automatically creates a POST endpoint — the function code stays on the server. The client sends form data, the server executes the function, and the response updates the page.

Using with Forms

Server Actions work directly with HTML forms via the action prop:

JSX
async function ContactPage() {
  async function submitForm(formData: FormData) {
    'use server';
    await sendEmail(formData.get('email'), formData.get('message'));
    redirect('/thank-you');
  }
  
  return (
    <form action={submitForm}>
      <input name="email" type="email" required />
      <textarea name="message" required />
      <button type="submit">Send</button>
    </form>
  );
}

Progressive Enhancement: This form works even with JavaScript disabled — the browser submits the form as a standard POST request. With JavaScript enabled, Next.js intercepts the submission for a smoother experience (no full page reload).

Separate Action Files

For reusable actions, create a file with 'use server' at the top:

JavaScript
// app/actions.ts
'use server';
 
export async function createUser(formData: FormData) {
  // Runs on server — safe to use secrets, database connections
  const user = await db.users.create(...);
  revalidatePath('/users');
  return user;
}

These can be imported by both Server and Client Components.

Pending States with useActionState

useActionState (React 19) provides form state and pending status:

JSX
'use client';
import { useActionState } from 'react';
import { createUser } from './actions';
 
function SignupForm() {
  const [state, formAction, isPending] = useActionState(createUser, null);
  
  return (
    <form action={formAction}>
      <input name="email" />
      <button disabled={isPending}>
        {isPending ? 'Creating...' : 'Sign Up'}
      </button>
      {state?.error && <p className="error">{state.error}</p>}
    </form>
  );
}

Optimistic Updates

useOptimistic shows the expected result immediately while the server processes:

JavaScript
'use client';
import { useOptimistic } from 'react';
 
function TodoList({ todos }) {
  const [optimisticTodos, addOptimistic] = useOptimistic(todos,
    (state, newTodo) => [...state, { ...newTodo, pending: true }]
  );
  
  async function addTodo(formData: FormData) {
    addOptimistic({ title: formData.get('title') });
    await createTodo(formData);
  }
  
  return <form action={addTodo}>...</form>;
}

Security

Server Actions are secure by default:

  • Function code never ships to the client — only a reference ID
  • Secrets, database connections, and internal logic stay on the server
  • Always validate input — Server Actions are POST endpoints, so malicious clients can call them with arbitrary data
  • Use authentication checks inside every action that modifies data

Revalidation After Mutations

After a mutation, update the UI by revalidating cached data:

  • revalidatePath('/posts') — revalidate a specific route
  • revalidateTag('posts') — revalidate all fetches tagged 'posts'
  • redirect('/success') — redirect to a new page

Key Interview Distinction

Server Actions are async functions with 'use server' that handle mutations from forms and event handlers. They replace API routes for data writes. Progressive enhancement means forms work without JavaScript. useActionState provides pending states. useOptimistic shows immediate UI feedback. Always validate inputs — Server Actions are POST endpoints that can receive arbitrary data. Revalidate cached data after mutations with revalidatePath/revalidateTag.

Fun Fact

Server Actions were inspired by PHP — the original 'server action' pattern where form submissions went directly to server-side code. React and Next.js essentially reinvented the PHP form handling model with modern ergonomics: type safety, optimistic UI, streaming updates, and progressive enhancement. The React team has joked that they've come 'full circle' back to server-side form processing.

Learn These First

Server & Client Components

intermediate

File-Based Routing

intermediate

Continue Learning

Route Handlers & API Routes

intermediate

Caching & Revalidation

advanced

Data Fetching

intermediate

Practice What You Learned

What are Server Actions in Next.js and how do they handle form submissions and mutations?
senior
server-actions
Server Actions are async functions that execute on the server, marked with 'use server'. They enable secure data mutations directly from components without creating API routes, support progressive enhancement (forms work without JavaScript), and integrate seamlessly with React's form handling and optimistic updates.
Previous
File-Based Routing
Prev