Зарегистрируйтесь, чтобы продолжить обучение

Состояние форм JS: Архитектура фронтенда

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

В документации React такие подходы называют контролируемыми и неконтролируемыми формами. Эти названия довольно точно описывают происходящее, поэтому здесь мы будем использовать ту же терминологию.

Неконтролируемые формы

Подход, при котором состояние формы хранится внутри самой формы и извлекается только при ее отправке. Это привычный способ работы с формой вне фреймворков:

form.addEventListener('submit', (e) => {
  const formData = new FormData(e.target);
  // Обработка данных, например, отправка на сервер
});

К достоинствам этого способа относят:

  • Простоту. Мало кода, не нужно хранить состояние.
  • Скорость. Браузер делает всю работу сам. Минимум вмешательства со стороны пользовательского кода.

Несмотря на легкость и очевидность, этот подход обладает одним недостатком. При таком подходе невозможно реагировать на изменения формы в процессе ее заполнения. Где это может быть нужно? Вот несколько примеров:

  • Автодополнение. Выпадающие списки зависят от того, что было набрано.
  • Валидация в процессе набора. Часто реализуется в виде красной рамки вокруг поля для ввода.
  • Моментальная фильтрация. Такое часто используется на сервисах бронирования или поиска товаров. Достаточно выбрать какой-то пункт меню, как сразу же меняется выборка.

В такой ситуации нам понадобятся контролируемые формы.

Контролируемые формы

При таком подходе состояние всех элементов формы отслеживается кодом приложения. Любое изменение анализируется и сохраняется. В зависимости от текущего состояния данных, код принимает решение что показать, а что нет. В таких формах зачастую даже нет кнопки отправки. Особенно там, где формы выполняют фильтрацию данных.

const state = {
  registrationForm: {
    state: 'valid',
    data: {
      name: '',
      email: '',
    },
    errors: [],
  },
};

// https://github.com/sindresorhus/on-change
const watchedState = onChange(state, (path, value) => {
  if (path === 'registrationForm.state') {
    if (value === 'invalid') {
      // Отрисовка ошибок, хранящихся где-то в состоянии
      // watchedState.registrationForm.errors
    }
  }
});

form.elements.name.addEventListener('change', (e) => {
  watchedState.registrationForm.data.name = e.target.value;
  // Действия: валидация, запросы, ...
});
form.elements.email.addEventListener('change', (e) => {
  watchedState.registrationForm.data.email = e.target.value;
  // Действия: валидация, запросы, ...
});

Если понадобится отправить эту форму, то сделать это будет даже проще, чем с неконтролируемыми формами. Данные уже извлечены из формы и готовы к отправке.

form.addEventListener('submit', (e) => {
  // Обработка данных, например, отправка на сервер
  // watchedState.registrationForm.data
});

Преимущества такого подхода:

  • Позволяет реализовать любую реакцию во время изменения формы до или вместо ее отправки.

И недостатки:

  • Значительно больше кода при ручной реализации.
  • Они медленнее из-за большего числа действий (и возможно тяжелой реакции). Но проблема это или нет – зависит от конкретной ситуации.

Контролируемые формы требуют настолько больше кода, что работу с ними всячески пытаются автоматизировать. Создают библиотеки, например, garlic.js, которые в автоматическом режиме отслеживают изменение формы и предоставляют колбеки для реакции на эти изменения.

Особенно таких библиотек много для разных фреймворков. Например, в React их десятки.

Что использовать?

В чистом JS предпочтительнее неконтролируемые формы. Так намного проще и быстрее. И только в том случае, когда нужна мгновенная реакция, можно вводить контроль данных формы. Причем не обязательно переходить от одного способа к другому целиком. Можно использовать гибрид, вводить контроль только тех данных, где без этого никак.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 25 000 ₸ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 26 декабря
профессия
от 39 525 ₸ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 26 декабря

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»