Добавить в корзинуПозвонить
Найти в Дзене

Как написать кастомный хук для управления формой

Управление формами в React всё ещё частая боль. Библиотеки вроде Formik или React Hook Form решают задачу, но иногда вам нужен лёгкий, прозрачный и контролируемый подход без зависимостей. Особенно если форма небольшая, а требования простые: поля, валидация, сброс. В этой статье мы напишем универсальный кастомный хук useForm, который: Начнём с базового состояния. Форма — это объект, где ключи = имена полей, значения = их текущее содержимое. Теперь добавим обработчик изменения: Этот подход работает с любыми полями: <input>, <select>, даже кастомными компонентами. Валидация должна быть: Создадим тип для правил: Пример схемы: Теперь добавим состояние ошибок и функцию валидации: Обратите внимание: мы передаём все значения формы в правило это позволяет делать кросс-валидацию (например, «пароли должны совпадать»). Сброс должен возвращать форму в изначальное состояние, включая очистку ошибок: Если нужно сбросить к новому набору значений, можно сделать reset(values) но для простоты оста
Оглавление

Управление формами в React всё ещё частая боль. Библиотеки вроде Formik или React Hook Form решают задачу, но иногда вам нужен лёгкий, прозрачный и контролируемый подход без зависимостей. Особенно если форма небольшая, а требования простые: поля, валидация, сброс.

В этой статье мы напишем универсальный кастомный хук useForm, который:

  • отслеживает значения полей,
  • поддерживает валидацию по правилам,
  • позволяет сбрасывать форму к начальному состоянию,
  • легко расширяется под любые нужды.

Основа: состояние формы

Начнём с базового состояния. Форма — это объект, где ключи = имена полей, значения = их текущее содержимое.

-2

Теперь добавим обработчик изменения:

-3

Этот подход работает с любыми полями: <input>, <select>, даже кастомными компонентами.

Валидация: гибкая и читаемая

Валидация должна быть:

  • настраиваемой (разные правила для разных полей),
  • реактивной (ошибки обновляются при изменении),
  • не мешающей UX (например, не показывать ошибку до первого взаимодействия).

Создадим тип для правил:

-4

Пример схемы:

-5

Теперь добавим состояние ошибок и функцию валидации:

-6

Обратите внимание: мы передаём все значения формы в правило это позволяет делать кросс-валидацию (например, «пароли должны совпадать»).

Сброс формы

Сброс должен возвращать форму в изначальное состояние, включая очистку ошибок:

-7

Если нужно сбросить к новому набору значений, можно сделать reset(values) но для простоты оставим базовый вариант.

Сборка хука

Объединим всё:

-8

Как использовать

-9

Как расширить

Хук легко адаптировать под ваши нужды:

  • Touched-состояние: добавьте touched: Record<string, boolean>, обновляйте при onBlur.
  • Асинхронная валидация: расширьте validateField до async, используйте useEffect для проверки уникальности email.
  • Поддержка вложенных полей: замените name: string на path: string и используйте lodash.set.

Почему это лучше библиотек?

  • Полный контроль: вы видите каждую строчку логики.
  • Минимальный размер: 0 зависимостей, ~1 KB gzip.
  • Легко тестируется: просто вызовите хук в юнит-тесте.
  • Гибкость: подстройте под любую архитектуру.

Конечно, для сложных форм (динамические поля, вложенные массивы, drag-and-drop) берите React Hook Form. Но для 80% случаев кастомный хук идеальный баланс.

Управление формой не повод тянуть тяжёлую библиотеку. С 50 строками кода вы получаете:

  • реактивные значения,
  • гибкую валидацию,
  • мгновенный сброс,
  • чистый и понятный API.

И самое главное вы понимаете, как это работает. А это бесценно.

Попробуйте внедрить useForm в свой следующий проект. Возможно, вы больше никогда не вернётесь к внешним зависимостям для простых форм.