← Усі статті

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.