webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
Next.js · Урок 8 из 12

Server Actions и формы

Безопасные мутации, useActionState, валидация и оптимистичный UI.

Обновлено

Что такое Server Action

Server Action — async-функция с пометкой 'use server', которую вы вызываете из интерфейса (форма, кнопка), но которая выполняется на сервере. Next автоматически создаёт эндпоинт и делает запрос за вас.

Их используют для мутаций: создание, редактирование, удаление, сохранение. Они заменяют связку «API-маршрут + fetch + состояние загрузки» для ваших собственных форм.

// features/create-post/api/create-post.ts
'use server'

import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'

export async function createPost(prev: State, formData: FormData) {
  const session = await auth()
  if (!session) return { error: 'Нет доступа' }

  const title = String(formData.get('title') ?? '').trim()
  if (title.length < 3) return { error: 'Слишком короткий заголовок' }

  const post = await db.post.create({ data: { title, authorId: session.userId } })
  updateTag('posts')
  redirect(`/posts/${post.id}`)
}

Это приложение сохраняет ваш прогресс ровно так (entities/progress/api/save-progress.ts).

Безопасность — самое важное

Server Action — это публичный POST-эндпоинт. Любой может вызвать его напрямую, без вашего интерфейса, с любыми данными.

  • Проверяйте аутентификацию и авторизацию в каждом действии («вошёл ли?» и «есть ли доступ к этому ресурсу?»).
  • Валидируйте весь ввод (zod / valibot) — в formData может быть что угодно.
  • Не возвращайте чувствительные данные.

Способы вызвать Server Action

Способ Код Когда
<form action={fn}> получает FormData по умолчанию для форм; работает даже без JS
useActionState(fn, initial) получаете [state, action, pending] показать ошибки / сообщения / pending
<button formAction={fn}> несколько действий в одной форме «Сохранить» и «Удалить»
прямой вызов в обработчике await fn(args) взаимодействия, не являющиеся формами (лайк, автосохранение)

Форма с useActionState

'use client'
import { useActionState } from 'react'

export function PostForm() {
  const [state, action, pending] = useActionState(createPost, { error: null })
  return (
    <form action={action}>
      <input name="title" required />
      <p aria-live="polite">{state.error}</p>
      <button disabled={pending}>{pending ? 'Сохранение…' : 'Сохранить'}</button>
    </form>
  )
}

С useActionState действие получает предыдущее состояние первым аргументом, а FormData — вторым.

Progressive enhancement: форма, отрендеренная на сервере с Server Action, работает, даже если JS ещё не загрузился.

Полный сценарий с валидацией Zod и сохранением значений после ошибки — в Формы с Server Actions.

Оптимистичный UI

const [optimisticLikes, addLike] = useOptimistic(likes, (state, n: number) => state + n)

<form action={async () => { addLike(1); await like(postId) }}>

Интерфейс меняется мгновенно; если действие не удалось, React вернёт реальное значение.

Server Action или Route Handler

Server Action Route Handler
формы и кнопки вашего приложения API для других (мобильные, партнёры)
мутации вебхуки (Stripe, CMS)
вызываются последовательно, по одному ответы не в HTML (RSS, файлы, публичный JSON)

Чтение данных через Server Actions не делают — для этого есть Server Components.

Коротко

  • Server Action = функция 'use server', вызываемая из UI и выполняемая на сервере; для мутаций.
  • В каждом действии: аутентификация + авторизация + валидация.
  • <form action> + useActionState для ошибок и pending; updateTag после мутации.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.