Серверные действия для форм
Серверное действие (server action) — асинхронная функция, которая выполняется на сервере, но её можно передать форме прямо в атрибут action. При отправке формы Next.js сам сделает запрос и вызовет функцию с данными формы. Отдельный API для этого писать не нужно.
Функция добавления статьи
Сначала добавьте в lib/posts.ts функцию, которая сохраняет статью:
// lib/posts.ts (добавить в конец)
export async function addPost(post: Post): Promise<void> {
posts.push(post);
}Пока статьи живут в массиве в памяти и пропадут после перезапуска сервера. В уроке о базе данных код этой функции поменяется, а форма останется прежней.
Файл с действиями
Создайте файл app/posts/actions.ts. Директива 'use server' в первой строке делает все экспортированные функции файла серверными действиями:
// app/posts/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { addPost } from '@/lib/posts';
export async function createPost(formData: FormData) {
const title = String(formData.get('title'));
const slug = String(formData.get('slug'));
const body = String(formData.get('body'));
await addPost({ slug, title, body });
revalidatePath('/posts');
redirect(`/posts/${slug}`);
}Действие получает объект FormData — значения полей по их атрибуту name. После сохранения revalidatePath обновляет список статей, а redirect отправляет посетителя на новую статью.
Форма
Страница /posts/new уже есть. Подключите к ней действие:
// app/posts/new/page.tsx
import { createPost } from '../actions';
export default function NewPostPage() {
return (
<form action={createPost}>
<h1>Новая статья</h1>
<input name="title" placeholder="Заголовок" required />
<input name="slug" placeholder="Адрес, например my-first-post" required />
<textarea name="body" placeholder="Текст статьи" required />
<button type="submit">Опубликовать</button>
</form>
);
}Откройте /posts/new, заполните поля и нажмите «Опубликовать». Браузер перейдёт на страницу новой статьи, а она появится и в списке /posts.
Что происходит при отправке
- Браузер отправляет данные формы на сервер.
- Next.js вызывает
createPostс этими данными. - Функция сохраняет статью и сбрасывает кеш списка.
redirectпереводит посетителя на страницу статьи.
Страница — серверный компонент, 'use client' не понадобился. Форма работает даже до загрузки JavaScript в браузере.
Безопасность
Серверное действие — это, по сути, открытый адрес на сервере: его может вызвать кто угодно, не только ваша форма. Поэтому внутри действия проверяют данные (следующий урок) и права пользователя (урок об авторизации).
Частая ошибка
Вызывать redirect внутри try...catch. Как и notFound(), она работает через специальное исключение, и catch его поглотит — перехода не будет. Ставьте redirect после блока try, в самом конце действия.