Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Серверные действия для форм

Серверное действие (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.

Что происходит при отправке

  1. Браузер отправляет данные формы на сервер.
  2. Next.js вызывает createPost с этими данными.
  3. Функция сохраняет статью и сбрасывает кеш списка.
  4. redirect переводит посетителя на страницу статьи.

Страница — серверный компонент, 'use client' не понадобился. Форма работает даже до загрузки JavaScript в браузере.

Безопасность

Серверное действие — это, по сути, открытый адрес на сервере: его может вызвать кто угодно, не только ваша форма. Поэтому внутри действия проверяют данные (следующий урок) и права пользователя (урок об авторизации).

Частая ошибка

Вызывать redirect внутри try...catch. Как и notFound(), она работает через специальное исключение, и catch его поглотит — перехода не будет. Ставьте redirect после блока try, в самом конце действия.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.