Пожалуй, одна из самых неприятных задач в 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
принимает в качестве параметра объект конфигураций. Эти конфигурации могут быть использованы для изменения и формирования формы по вашему желанию.
В этом руководстве вы будете использовать передачу следующих свойств объекта:
-
initialValues
: включает поля формы и их начальные значения. -
validationSchema
: Схема Yup для проверки полей. Вы будете использовать ее в следующем разделе. -
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
включает в себя следующие свойства:
-
handleSubmit
: функция отправки, которая должна быть вызвана при отправке формы. Обычно она назначается обработчику событияonSubmit
элементовform
. -
errors
: Объект, который имеет имена полей в качестве свойств, а значением каждого из них является сообщение об ошибке, полученное в результате проверки этого поля, если есть какие-либо ошибки. -
touched
: Объект, который имеет имена полей в качестве свойств, а значением является булево число, указывающее, взаимодействовал ли пользователь с полем или нет. -
values
: Объект, у которого имена полей являются свойствами, а значение каждого из них — текущее значение этого поля. Обычно используется для установки свойстваvalue
элементов ввода. -
handleChange
: Функция, которая должна использоваться в качестве обработчика события изменения элементов ввода. Она передается как значение свойстваonChange
элементов. -
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()
})
})
Вы добавляете следующие правила валидации:
-
name
: должно быть строкой и является обязательным. Вы также используете методlabel
для того, чтобы при выводе сообщения об ошибке поле называлось «Полное имя». По умолчанию на поля ссылаются по имени поля, которое в данном случаеname
. -
email
: Должен быть строкой, электронной почтой, и является обязательным. -
profession
: Должно быть строкой и одним из значений массиваprofessions
. Вы также передаете сообщение в качестве второго параметра вoneOf
, которое будет сообщением, показываемым в случае ошибки. Также требуется. -
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 более простым и менее напряженным.