← Все статьи

React 19 Form Actions и FastAPI: валидация на сервере без дублирования

useActionState + Pydantic: одна схема, структурированные ошибки по полям, isPending из коробки — минус ~50% кода форм.

Содержание

Коротко

Классическая схема форм — Pydantic на бэкенде, Zod на фронте, ручные useState и useTransition. Автор CitizenApp показывает связку React 19 Form Actions с FastAPI: правила валидации живут один раз на сервере, клиент получает структурированные ошибки через useActionState.

Что произошло

«Старый путь» держит логику формы в пяти местах: схема Pydantic, дубликат в Zod, REST-эндпоинт, ручные сообщения об ошибках, колбэки отправки. Новое правило валидации — правки минимум в трёх файлах; если клиент прошёл, а сервер отклонил — пользователь видит спиннер и общую ошибку.

Паттерн: форма отправляется в server action (функция с 'use server'), action вызывает FastAPI, FastAPI валидирует тело через Pydantic и возвращает 422 с деталями или успешный ответ. useActionState даёт [state, formAction, isPending] — состояние загрузки и ошибки по полям без отдельных хуков.

Схема на сервере — единственный источник правды. TypeScript-типы можно генерировать из Pydantic (datamodel-code-generator). В JSX ошибки фильтруются по field и показываются рядом с инпутами.

Почему это важно

Дублирование валидации — один из главных источников багов в full-stack приложениях. Серверная проверка обязательна (клиент обходится), но клиентская «для UX» часто расходится с бэкендом. Централизация на Pydantic убирает рассинхрон.

Server action как мост скрывает FastAPI от браузера: чувствительные операции не попадают в клиентский код. isPending блокирует кнопку без useState. Автор оценивает сокращение кода форм примерно вдвое.

Подводный камень: формат 422 от FastAPI — массив detail с loc (кортеж, имя поля на индексе 1) и msg. Трансформацию в { field, message } нужно написать один раз осознанно.

На практике

  1. Определите Pydantic-модель запроса и ответа с errors: list[ValidationError].
  2. Server action собирает FormData, шлёт JSON на FastAPI, мапит 422 в ваш формат.
  3. Подключите useActionState(action, null) — не дублируйте loading state.
  4. Рендерите ошибки по state.errors.filter(e => e.field === 'email').
  5. Сгенерируйте TS-типы из Python-схем, не копируйте вручную.
  6. Кастомные сообщения — через Field(description=...) в Pydantic.

Итог

React 19 Form Actions + FastAPI — практичный выход из ада «две схемы, два набора сообщений». Не замена клиентской валидации для мгновенного UX, но надёжная основа для отправки. Пошаговый код — в оригинале на Dev.to.