Как создавать и проверять формы в React с помощью Formik и Yup

Пожалуй, одна из самых неприятных задач в React — создание форм и их валидация, особенно если вы делаете это без использования каких-либо библиотек. Вам придется управлять состояниями, значениями и валидацией всех вводимых данных.

Formik — это библиотека React и React Native, которая поможет вам создавать формы в React «без слез». Вы можете использовать Formik в паре с библиотеками валидации, такими как Yup, чтобы сделать процесс еще проще.

В этом уроке вы узнаете, как можно упростить создание и проверку форм в React с помощью Formik и Yup. Вы создадите простую форму с различными типами полей и увидите различные способы проверки этой формы.

Код для этого руководства вы можете найти в этом репозитории GitHub.

Настройка проекта

В этом разделе вы настроите свой сайт с помощью Create React App (CRA) и установите некоторые зависимости для данного руководства. Если у вас уже есть созданный сайт, вы можете пропустить эту часть.

В терминале выполните следующую команду, чтобы создать новый сайт React с помощью CRA:

npx create-react-app react-forms
Войти в полноэкранный режим Выйти из полноэкранного режима

Я назвал сайт react-forms, но вы можете изменить его на любой другой.

После завершения установки перейдите в только что созданную директорию:

cd react-forms
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем установите Tailwind CSS, чтобы добавить некоторые стили на ваш сайт:

npm install -D tailwindcss postcss autoprefixer
Войти в полноэкранный режим Выйти из полноэкранного режима

Для установки Tailwind CSS создайте файл tailwind.config.js со следующим содержимым:

module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Войти в полноэкранный режим Выйти из полноэкранного режима

И замените содержимое файла src/index.css на следующее:

@tailwind base;
@tailwind components;
@tailwind utilities;
Войти в полноэкранный режим Выйти из полноэкранного режима

Создание формы с помощью Formik

Сейчас вы будете использовать Formik для создания формы. Сначала установите Formik:

npm i formik
Войти в полноэкранный режим Выйти из полноэкранного режима

Замените содержимое src/App.js на следующее:

import { useFormik } from 'formik';

function App() {
    const professions = ['Developer', 'Designer', 'Other'];
    //TODO create formik instance

    return (
        <div className="bg-blue-300 min-w-screen min-h-screen overflow-x-hidden">
        </div>
    );
}

export default App;
Войти в полноэкранный режим Выйти из полноэкранного режима

Все, что вы сделали здесь, это создали компонент App, который на данный момент не делает ничего особенного.

Обратите внимание, как вы импортировали хук useFormik в начале файла. Вы будете использовать этот хук для создания экземпляра Formik со всеми состояниями и помощниками, которые вам понадобятся.

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

В этом руководстве вы будете использовать передачу следующих свойств объекта:

  1. initialValues: включает поля формы и их начальные значения.
  2. validationSchema: Схема Yup для проверки полей. Вы будете использовать ее в следующем разделе.
  3. onSubmit: функция, выполняемая при отправке формы.

Замените TODO в компоненте App на следующее:

const formik = useFormik({
    initialValues: {
      name: '',
      email: '',
      profession: professions[0],
      age: '',
    },
    onSubmit: function (values) {
      alert(`You are registered! Name: ${values.name}. Email: ${values.email}. Profession: ${values.profession}. 
        Age: ${values.age}`);
    }
  })
Войти в полноэкранный режим Выйти из полноэкранного режима

Как вы видите, вы установили значение свойства initialValues в объект. Ключи этого объекта — это имена полей формы. Их значения — это начальное значение.

В функции onSubmit вы получаете объект values в качестве параметра. Здесь вы можете получить доступ к значениям и использовать их для сохранения в базе данных или отправки на сервер. В данном учебнике вы просто выведете их в оповещение.

Обратите внимание, что функция onSubmit выполняется только после проверки формы. Поэтому вам не нужно выполнять валидацию внутри этой функции.

Теперь вы можете использовать переменную formik для создания формы, связать ее поля с полями, которые вы определили в useFormik, связать проверку и обработчик отправки.

formik включает в себя следующие свойства:

  1. handleSubmit: функция отправки, которая должна быть вызвана при отправке формы. Обычно она назначается обработчику события onSubmit элементов form.
  2. errors: Объект, который имеет имена полей в качестве свойств, а значением каждого из них является сообщение об ошибке, полученное в результате проверки этого поля, если есть какие-либо ошибки.
  3. touched: Объект, который имеет имена полей в качестве свойств, а значением является булево число, указывающее, взаимодействовал ли пользователь с полем или нет.
  4. values: Объект, у которого имена полей являются свойствами, а значение каждого из них — текущее значение этого поля. Обычно используется для установки свойства value элементов ввода.
  5. handleChange: Функция, которая должна использоваться в качестве обработчика события изменения элементов ввода. Она передается как значение свойства onChange элементов.
  6. handleBlur: Функция, которая должна использоваться в качестве обработчика события размытия элементов ввода. Она передается как значение свойства onBlur элементов.

Замените оператор return в App на следующий:

    return (
        <div className="bg-blue-300 min-w-screen min-h-screen overflow-x-hidden">
          <form onSubmit={formik.handleSubmit} className="max-w-lg mx-auto bg-white rounded shadow-lg mt-7 p-3">
          <h1 className='text-3xl mb-3 text-center'>Register</h1>
            <div className='mb-4'>
              <label for="name">Full Name</label>
              <input type="text" name="name" id="name" 
                className={`block w-full rounded border py-1 px-2 ${formik.touched.name && formik.errors.name ? 'border-red-400' : 'border-gray-300'}`}
                onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.name} />
              {formik.touched.name && formik.errors.name && (
                <span className='text-red-400'>{formik.errors.name}</span>
              )}
            </div>
            <div className='mb-4'>
              <label for="email">Email</label>
              <input type="email" name="email" id="email"
                className={`block w-full rounded border py-1 px-2 ${formik.touched.email && formik.errors.email ? 'border-red-400' : 'border-gray-300'}`}
                onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.email} />
              {formik.touched.email && formik.errors.email && (
                <span className='text-red-400'>{formik.errors.email}</span>
              )}
            </div>
            <div className='mb-4'>
              <label for="profession">Profession</label>
              <select name="profession" id="profession"
                className={`block w-full rounded border py-1 px-2 ${formik.touched.profession && formik.errors.profession ? 'border-red-400' : 'border-gray-300'}`}
                onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.profession} >
                {professions.map((profession, index) => (
                  <option value={profession} key={index}>{profession}</option>
                ))}
              </select>
              {formik.touched.profession && formik.errors.profession && (
                <span className='text-red-400'>{formik.errors.profession}</span>
              )}
            </div>
            <div className='mb-4'>
              <label for="age">Age</label>
              <input type="number" name="age" id="age"
                className={`block w-full rounded border py-1 px-2 ${formik.touched.age && formik.errors.age ? 'border-red-400' : 'border-gray-300'}`}
                onChange={formik.handleChange} onBlur={formik.handleBlur} value={formik.values.age} />
              {formik.touched.age && formik.errors.age && (
                <span className='text-red-400'>{formik.errors.age}</span>
              )}
            </div>
            <div className='text-center'>
              <button className='bg-blue-500 rounded p-3 text-white' type='submit'>Submit</button>
            </div>
          </form>
        </div>
      );
Войти в полноэкранный режим Выйти из полноэкранного режима

Обратите внимание, как вы использовали все свойства переменной formik, упомянутой ранее.

Протестируйте

Теперь форма создана и готова к использованию, даже если еще нет валидации.

Чтобы протестировать ее, запустите сервер с помощью следующей команды:

npm start
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем вы можете открыть веб-сайт по адресу localhost:3000 (порт по умолчанию). Если вы откроете веб-сайт, вы увидите форму с 4 полями.

Вы можете попробовать заполнить форму. Поскольку в настоящее время нет валидации, вы можете заполнить (или не заполнить) значения, какие хотите, и нажать Submit. Появится оповещение с введенными вами значениями.

Добавление валидации с помощью Yup

В этом разделе вы добавите валидацию в форму с помощью Yup.

Сначала вам нужно установить Yup. Запустите в терминале следующую команду:

npm i yup
Войти в полноэкранный режим Выйти из полноэкранного режима

Yup имеет множество методов и правил валидации, которые вы можете использовать. Как это работает с Formik, вам нужно создать схему валидации и передать ее в useFormik как значение свойства validationSchema.

Схемы валидации Yup создаются с помощью метода Yup.object, который принимает в качестве параметра объект. Этот объект имеет имена полей в качестве свойств, а их значения являются правилами валидации из библиотеки Yup.

Импортируйте Yup в начало src/App.js:

import * as Yup from 'yup';
Войти в полноэкранный режим Выйти из полноэкранного режима

Затем добавьте свойство validationSchema к объекту, передаваемому в useFormik со следующим значением:

const formik = useFormik({
    ...,
    validationSchema: Yup.object({
      name: Yup.string()
              .label('Full Name')
              .required(),
      email: Yup.string()
              .email()
              .required(),
      profession: Yup.string()
                  .oneOf(professions, 'The profession you chose does not exist'),
      age: Yup.number()
            .min(15, 'You need to be older than 15 to register')
            .required()
    })
  })
Войти в полноэкранный режим Выйти из полноэкранного режима

Вы добавляете следующие правила валидации:

  1. name: должно быть строкой и является обязательным. Вы также используете метод label для того, чтобы при выводе сообщения об ошибке поле называлось «Полное имя». По умолчанию на поля ссылаются по имени поля, которое в данном случае name.
  2. email: Должен быть строкой, электронной почтой, и является обязательным.
  3. profession: Должно быть строкой и одним из значений массива professions. Вы также передаете сообщение в качестве второго параметра в oneOf, которое будет сообщением, показываемым в случае ошибки. Также требуется.
  4. age: должно быть числом и не менее 15. Если возраст меньше 15, появится сообщение «You need to be older than 15 to register». Это также обязательно.

Проверить

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

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

Пользовательские правила валидации

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

В этом разделе вы добавите правило, чтобы убедиться, что в поле name есть и имя, и фамилия.

Измените свойство name внутри validationSchema на следующее:

const formik = useFormik({
    ...,
    validationSchema: Yup.object({
      name: Yup.string()
              .label('Full Name')
              .required()
              .test('is-full-name', 'Please enter both your first and last name', function (value) {
                const nameArr = value.split(" ");
                return nameArr.length >= 2;
              }),
      ...
    })
  })
Войти в полноэкранный режим Выйти из полноэкранного режима

Первый параметр — это имя пользовательского правила. Второй параметр — это сообщение, которое будет показано в случае, если поле недействительно.

Третий параметр — функция, определяющая, является ли поле действительным или нет. Она должна возвращать булево значение. Если значение равно true, то поле действительно. В противном случае оно недействительно.

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

Проверьте это

Запустите сервер снова и перейдите на веб-сайт. Если вы введете одно слово в поле Полное имя, вы увидите ошибку.

Чтобы поле было действительным, вам нужно ввести не менее двух слов.

Заключение

В этом руководстве вы узнали, как использовать Formik и Yup в React. Вы можете использовать эти две библиотеки для создания форм, их проверки и обработки отправки. Использование этих двух библиотек делает создание форм в React более простым и менее напряженным.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *