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.