Next.js Data

Server Actions

Form actions, revalidation, optimistic updates, and progressive enhancement.

Advertisement

Server Actions

Form actions, revalidation, optimistic updates, and progressive enhancement.

Overview

Server Actions enable server-side mutations without API routes.

Key Concepts

  • Server Functions — Functions that run on the server
  • Form Actions — Native form submission
  • Revalidation — Update cached data
  • Optimistic Updates — UI updates before server response
  • Error Handling — Server-side error handling

Code Examples

// app/actions.js
'use server';
import { revalidatePath, revalidateTag } from 'next/cache';
import { redirect } from 'next/navigation';

export async function createPost(formData) {
  const title = formData.get('title');
  const content = formData.get('content');

  // Validate
  if (!title || title.length < 3) {
    return { error: 'Title must be at least 3 characters' };
  }

  // Create in database
  const post = await db.posts.create({
    data: { title, content, authorId: getCurrentUser().id }
  });

  // Revalidate and redirect
  revalidatePath('/posts');
  redirect(`/posts/${post.id}`);
}

// Optimistic updates
'use client';
import { useOptimistic } from 'react';

function TodoList({ todos }) {
  const [optimisticTodos, addOptimisticTodo] = useOptimistic(
    todos,
    (state, newTodo) => [...state, { ...newTodo, pending: true }]
  );

  async function handleSubmit(formData) {
    const title = formData.get('title');
    addOptimisticTodo({ id: crypto.randomUUID(), title, pending: true });
    await createTodo(formData);
  }

  return (
    <div>
      <form action={handleSubmit}>
        <input name="title" />
        <button type="submit">Add</button>
      </form>
      <ul>
        {optimisticTodos.map(todo => (
          <li key={todo.id} style={{ opacity: todo.pending ? 0.5 : 1 }}>
            {todo.title}
          </li>
        ))}
      </ul>
    </div>
  );
}

Practice

Build a todo app with server actions and optimistic updates.