Валидация данных в React. Formik, yup. [Видео]

Это введение в валидицию с помощью Formik и Yup на примере простой страницы регистрации. Тут валидация подтверждения пароля, валидация email и прочих обязательных полей.

Валидация подтверждения пароля

В Yup идея проста. Существует метод yup.ref, который получает данные из какой-то ячейки формы (если она конечно есть). Нам нужно сравнить раны ли данные нашего поля данным в ref. Для этого мы используем метод yup.string().oneOf, который принимает массив допустимых значений (кстати так можно валидировать селекты) и сообщения, которое выведется если поля не валидное. Получается так:

password: yup.string()
  .typeError('Должно быть строкой') // Не обязательная строка
  .test('', '', () => { /* Дополнительная функция для проверки пароля */ })
  .matches(REG_EXP, 'Не соответствует правилу') // Проверка на соответствие регулярному выражению.
  .required('Обязательно'),
confirmPassword: yup.string()
  .oneOf([yup.ref('password')], 'Пароли не совпадают')
  .required('Обязательно') 

Валидация email

Всё просто:

email: yup.string()
 .matches(REG_EXP, 'Не соответствует правилу') // Проверка на соответствие регулярному выражению.
  .email('Введите верный email').required('Обязательно'),

Код из видео

import React from 'react';
import { Formik } from 'formik'
import * as yup from 'yup'
import './App.scss'


function App() {
  const validationsSchema = yup.object().shape({
    name: yup.string().typeError('Должно быть строкой').required('Обязательно'),
    secondName: yup.string().typeError('Должно быть строкой').required('Обязательно'),
    password: yup.string().typeError('Должно быть строкой').required('Обязательно'),
    confirmPassword: yup.string().oneOf([yup.ref('password')], 'Пароли не совпадают').required('Обязательно'),
    email: yup.string().email('Введите верный email').required('Обязательно'),
    confirmEmail: yup.string().email('Введите верный email').oneOf([yup.ref('email')], 'Email не совпадают').required('Обязательно')
  })

  return (
    <div>
      <Formik
        initialValues={{
          name: '',
          secondName: '',
          password: '',
          confirmPassword: '',
          email: '',
          confirmEmail: ''
        }}
        validateOnBlur
        onSubmit={(values) => { console.log(values) }}
        validationSchema={validationsSchema}
      >
        {({ values, errors, touched, handleChange, handleBlur, isValid, handleSubmit, dirty }) => (
          <div className={from}>
            <p>
              <label htmlFor={name}>Имя</label><br />
              <input
                className={'input'}
                type={text}
                name={name}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.name}
              />
            </p>
            {touched.name && errors.name && <p className={'error'}>{errors.name}</p>}
            <p>
              <label htmlFor={secondName}>Фамилия</label><br />
              <input
                className={'input'}
                type={text}
                name={secondName}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.secondName}
              />
            </p>
            {touched.secondName && errors.secondName && <p className={'error'}>{errors.secondName}</p>}
            <p>
              <label htmlFor={secondName}>Пароль</label><br />
              <input
                className={'input'}
                type={password}
                name={password}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.password}
              />
            </p>
            {touched.password && errors.password && <p className={'error'}>{errors.password}</p>}

            <p>
              <label htmlFor={confirmPassword}>Подтвердите пароль</label><br />
              <input
                className={'input'}
                type={password}
                name={confirmPassword}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.confirmPassword}
              />
            </p>
            {touched.confirmPassword && errors.confirmPassword && <p className={'error'}>{errors.confirmPassword}</p>}

            <p>
              <label htmlFor={email}>Email</label><br />
              <input
                className={'input'}
                type={email}
                name={email}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.email}
              />
            </p>
            {touched.email && errors.email && <p className={'error'}>{errors.email}</p>}

            <p>
              <label htmlFor={confirmEmail}>Подтвердите email</label><br />
              <input
                className={'input'}
                type={email}
                name={confirmEmail}
                onChange={handleChange}
                onBlur={handleBlur}
                value={values.confirmEmail}
              />
            </p>
            {touched.confirmEmail && errors.confirmEmail && <p className={'error'}>{errors.confirmEmail}</p>}

            <button
              disabled={!isValid || !dirty}
              onClick={handleSubmit}
              type={submit}
            >Отправить</button>
          </div>
        )}
      </Formik>
    </div>
  );
}

export default App;