Разбиваем Formik React Package, чтобы упростить управление формами
Перспектива ускорения разработки форм - очень привлекательная причина для принятия нового пакета: Enter Formik. Formik стремится убрать сложность и многословность форм в React, сохраняя при этом элементы как можно более простыми. Интеграция Formik для ваших форм сводит к минимуму следующие моменты:
- Управление состоянием формы - выполняется автоматически и локально. Такие пакеты, как Redux Forms, связывают состояние вашей формы с деревом состояний. Это означает, что ваш редуктор верхнего уровня вызывается при каждом нажатии клавиши. Это ненужные накладные расходы и плохой дизайн. Состояние формы должно быть локальным.
- Проверка формы - с помощью обработчиков проверки Formik и (необязательно) Ага. Мы можем свободно обрабатывать валидацию с помощью Formik, как нам заблагорассудится, однако вместо того, чтобы изобретать колесо, Formik также поддерживает Yup: наиболее широко используемое решение для проверки объектов для React, непосредственно в его обработчиках. (Подробнее про Ага здесь).
- Обработка отправки формы - простой синтаксический анализ значений и форматирование ошибок с помощью функций-обработчиков, переданных в Formik.
Это очень веские причины перейти на поезд Formik, однако онлайн-документация может показаться новичкам несколько разрозненной, с подробной документацией и ручками кода, которые принимают разные стили реализации.
Причина этого в том, что Formik предоставляет нам несколько способов создания форм: более традиционный рабочий процесс на основе компонентов для создания форм, а также более абстрактный метод, использующий «компонент более высокого порядка» с оболочкой класса withFormik
для управления опорой и обработчиком. .
В этой статье мы будем использовать прежний компонентный подход, применяя, среди прочего, <Formik />
и <Field />
components для создания наших форм Formik.
Мы рассмотрим, как создать форму с различными методами ввода (input, textarea, select и т. Д.), проверить ввод и отправить форму. Мы также рассмотрим некоторые другие встроенные обработчики Formik, такие как onBlur
, что позволяет нам выполнять некоторую проверку в реальном времени, когда пользователь перемещается по форме.
Предварительное чтение
Если вы еще не углубились в мир форм React, я рекомендую прочитать еще пару моих статей, чтобы сделать это чтение максимально полезным.
Элементы формы в React
В React элементы формы JSX привязаны к состоянию, что влияет на их функциональность и представление. Это отличает их от обычного HTML. Прочтите следующую статью, чтобы понять эти различия и то, как использовать компоненты для создания полезных элементов формы:
Ага: анализ и проверка объектов
Хотя это и не обязательно, знание того, как работает Yup, полезно и дает нам дополнительный уровень простоты при проверке форм. Если вы хотите прочитать о Ага, я написал статью, знакомящую с этим, почему вам стоит об этом позаботиться:
Установка и импорт Formik
Найдите пакет formik на NPMJS по адресу https://www.npmjs.com/package/formik.
Formik - это своего рода история успеха 2018 года, когда количество скачиваний увеличилось с 6 тыс. Еженедельно в начале года до 100 тыс. Загрузок в неделю в сентябре, при этом в октябре траектория роста все еще выглядит здоровой.
Как вы можете себе представить, учитывая внезапный всплеск популярности, Formik находится в активной разработке, поскольку сообщество продвигает концепцию и решает проблемы. Чтобы полностью изучить исходный код, посетите проект Github по адресу https://github.com/jaredpalmer/formik.
Установка Formik добавляет к вашему проекту размер Gzip размером 13,7 КБ на момент написания этой статьи; вполне разумный размер, учитывая его возможности.
Установите его с помощью следующей команды npm:
npm i formik
В этой статье мы будем импортировать в наш проект следующие компоненты Formik:
import { Formik, FormikProps, Form, Field } from 'formik';
Давайте кратко рассмотрим эти объекты, прежде чем использовать их для создания формы.
<Formik />
- наш самый главный компонент. Через его свойства мы настроим некоторые встроенные обработчики форм Formik, которые, по сути, позволяют нашей форме функционировать. Мы также будем использовать опоруrender
. Вся наша форма создается с помощью функции, переданной в эту опору.FormikProps
передается через вышеуказанную функциюrender
prop, которая дает нам доступ к состоянию нашей формы - значениям, ошибкам, касались ли ввод (выбран в первый раз), является ли форма представление и так далее.<Form />
- это простейший из наших операций импорта, который мы используем, чтобы просто обернуть наши поля. Следовательно, все<Field />
компоненты должны быть дочерними по отношению к<Form />
.<Field />
будет использоваться для обеспечения совместимости наших элементов с Formik. Другими словами, без компонента Field наши элементы ввода ничего не будут знать о Formik.<Field />
фактически предоставляет текстовое поле ввода в качестве метода ввода по умолчанию, а также параметры раскрывающегося списка и текстового поля.
Это означает, что мы можем визуализировать ввод, связанный с Formik, просто объявив компонент Field. Однако мы также можем передавать пользовательские компоненты, чтобы связать Formik с любым методом ввода, который мы хотим использовать.
Если это сложно визуализировать, в следующем разделе мы рассмотрим, как структурирована форма в нашей разметке JSX.
Структурирование формы Formik
Давайте посмотрим, как построить форму Formik. Давайте оставим наш пример формы простым и разберемся с 3 полями: имя, адрес электронной почты и пол.
Прежде чем перейти к полной реализации, давайте рассмотрим структуру формы Formik:
... import { Formik, FormikProps, Form, Field } from 'formik'; export class MyForm extends React.Component { handleSubmit = (values, { props = this.props, setSubmitting }) => { //process form submission here //done submitting, set submitting to false setSubmitting(false); return; } render() { return( <Formik initialValues={{ first_name: '', email: '', gender: '' }} validate={(values) => { let errors = {}; //check if my values have errors return errors; }} onSubmit={handleSubmit} render={formProps: FormikProps => { return( <Form> <Field ... /> <Field ... /> <Field ... /> <button type="submit" disabled={formProps.isSubmitting}> Submit Form </button> </Form> ); } />); } }
Здесь происходит немало даже для простой формы! Давайте разберемся, что происходит:
- Вся моя форма Formik размещена в компоненте MyForm.
- Сначала я определяю обработчик отправки формы, который позже будет передан в опору Formik. Обратите внимание на аргументы этой функции. первый -
values
: он содержит все мои значения формы, с которыми можно работать. Второй аргумент - это объект, позволяющий передавать наши свойства и методы Formik в обработчик отправки.setSubmitting
позволяет нам сообщить Formik, отправляется ли форма или нет, в виде логического значения. - Вся форма отображается в функции визуализации нашего компонента. Здесь ничего нового.
- Внутри рендера мы настраиваем
<Formik />
компонент и ничего больше. - Обратите внимание, как сама разметка нашей формы настроена в
render
опоре<Formik />
. Объект Formik также включает свойства для начальных значений, проверки и, конечно же, onSubmit и рендеринга.
Это общий шаблон формы Formik - мы передаем наши функции через реквизиты с помощью объектов Formik за кулисами, которые отлично справляются с организацией значений и ошибок формы, а также других вещей, выходящих за рамки нашего первого примера!
Создавая формы, мы меньше всего хотим беспокоиться о том, как манипулировать всем нашим состоянием, с ошибками, значениями и прочим. С Formik нам этого не нужно - он позволяет нам сосредоточиться на наших компонентах формы и обработке их взаимодействия.
Настройка Formik ‹Поле /›
Каждый из наших элементов формы должен сопровождаться <Field />
компонентом. По умолчанию мы можем использовать опору type="text"
для визуализации ввода текста.
Вот как это может выглядеть с некоторыми дополнительными функциями, которые мы вскоре рассмотрим:
<Field type="text" name="email" placeholder="Email Address" className='textbox' /> { formProps.touched.email && formProps.errors.email && <span className='error'>{formProps.errors.email}</span> }
Итак, мы определили наше первое поле с помощью Formik. Компонент <Field />
принимает реквизиты, которые мы могли бы ожидать от стандартного элемента ввода, такие как класс, имя, тип и заполнитель. Однако в React мы должны иметь дело с состоянием.
Что делает Formik, так это подключает наши входные значения к состоянию с помощью своей name
prop. В приведенном выше примере значение состояния будет сохранено как values.email
.
Но обратите внимание на код ниже <Field />
. Этот код имеет дело с отображением ошибки для этого конкретного поля. (Ошибка взята из нашего объекта formProps
, который Formik автоматически обновляет для нас - все, что вам нужно сделать, это не забыть передать formProps
внутри функции render
prop).
Мы отображаем эту ошибку только в том случае, если было затронуто поле электронной почты, и если ошибка существует - тогда мы обращаемся к ней через formProps.errors.email
.
Тем не мение…
Есть лучший способ отобразить эту ошибку, используя объект Formik <ErrorMessage />
.
‹ErrorMessage />
Object
Объект ErrorMessage отображает ошибку только в том случае, если к полю прикоснулись (или с ним прореагировали). Вместо того, чтобы писать это (сверху):
{ formProps.touched.email && formProps.errors.email && <span className='error'>{formProps.errors.email}</span> }
Мы можем просто написать это:
<ErrorMessage name="email" />
Намного более аккуратный синтаксис.
Примечание. Не забудьте импортировать ErrorMessage в свой импорт Formik.
Итак, чтобы генерировать наши ошибки, мы используем свойство Formik validate
. Это хорошо подводит нас к валидации.
Настройка проверки
Откуда взялось значение ошибки электронной почты? Помните нашу validate
опору, которую мы определили в объекте <Formik />
? И снова:
<Formik validate={(values) => { let errors = {}; //check if my values have errors return errors; }} ... />
Как видите, мы можем определять наши ошибки в объекте на основе значений нашей формы и возвращать ошибки, когда мы закончим. Отсюда Formik подберет их и поместит в formProps
. Как и formProps
, наш аргумент validate values
также управляется Formik - вам просто нужно не забыть передать его в этой функции проверки.
Теперь у нас есть 2 варианта проверки; первый - использовать нашу валидационную опору, как мы обсуждали выше, где мы можем сделать что-то вроде этого:
<Formik validate={(values) => { let errors = {}; if(!values.email || is_valid_email(values.email)) errors.email = 'Valid Email Address Required'; return errors; }} ... />
Мы также можем принять любую стороннюю библиотеку для использования в качестве средства проверки с помощью этого метода.
Второй способ - использовать Yup. Мы упомянули Yup в начале этой статьи, и вот почему. Мы действительно могли бы выполнить проверку Yup в нашей validate
опоре, однако Formik теперь поддерживает опору validationSchema
для автоматической проверки вашей формы на основе объекта Yup.
Вместо этого мы могли бы сделать что-то вроде этого:
//define my schema using Yup const formSchema = yup.object().shape({ ... }); <Formik validationSchema={formSchema} ... />
Примечание. Не забудьте импортировать да, с import * as yup from ‘yup’;
Как видите, использовать validationShema
и Ага намного проще и легче читать и управлять! Однако - если вам действительно нужны дополнительные функции, возможно, запрос API или веб-сокет для проверки доступного имени пользователя, в нашем распоряжении всегда есть свойство validate
.
Ознакомьтесь с этим руководством, чтобы глубже погрузиться в процесс валидации с помощью Formik.
Абстрагирование ваших обработчиков
Здесь стоит упомянуть, как вы представляете своих обработчиков в своих проектах.
Малые формы можно определять, как показано выше, но по мере их роста может потребоваться абстрагирование или рефакторинг ваших функций-обработчиков, чтобы проект оставался организованным.
По этой причине рекомендуется определять функции обработчика Formik вне самого объекта <Formik />
.
Взяв наш предыдущий пример, мы могли бы переопределить обработчики в нашем компоненте или импортировать их как модуль - вам решать, как лучше всего структурировать свой проект на основе ваших шаблонов проектирования.
Вот как может выглядеть импорт ваших функций:
import * as myForm from './forms/myForm'; export class MyForm extends React.Component { render() { return( <Formik initialValues={myForm.initialValues} validate={myForm.validate} onSubmit={myForm.onSubmit} render={ (formProps: FormikProps) => { <Form> <Field ... /> ... </Form> }} /> ); } }
Это делает вещи более удобочитаемыми, предоставляя большую часть площади экрана самой форме. Если в вашем компоненте размещается множество форм, то, возможно, стоит рассмотреть возможность рефакторинга самой разметки формы более абстрактным способом.
Использование других типов ввода с полем
Мы можем использовать другие типы ввода с полями. Фактически, свойство component
для <Field />
может принимать input
, select
и textarea
как строки. Мы также можем передавать компоненты в эту опору, что позволяет нам рендерить любой компонент, который мы пожелаем.
Тот же объект fieldProps
, упомянутый выше, плюс любые другие реквизиты можно передать непосредственно <Field />
.
Например, определение раскрывающегося списка выбора с помощью поля может выглядеть следующим образом:
<Field name="gender" component="select" placeholder="Your Gender"> <option value="male">Male</option> <option value="female">Female</option> </Field>
Чтобы избежать повторений в этой статье, обратитесь к Справочнику по API полей для получения дополнительной информации о настройке полей и о том, как передавать настраиваемые поля.
Итак, теперь мы к чему-то приближаемся. Теперь мы знаем:
- Что такое Формик и как структурировать форму Формика.
- Мы также знаем, как использовать
<Form />
и<Field />
для определения полей формы и что наши обработчики форм передаются в<Formik />
component. - Компонент Formik имеет дело с множеством магических объектов, и все, что нам нужно сделать, это не забыть передать их нашим обработчикам.
- Проверка может быть выполнена вручную через опору
validate
или с помощью Yup исключительно с помощьюvalidationSchema
. В любом случае, мы можем использовать сторонние пакеты в Formik для выполнения нашей проверки.
По общему признанию, Formik - это не простой пакет, в который можно просто перейти за 5 минут, что отражает многословность документации в Интернете. Хотя мы рассмотрели основы работы Formik, мы упустили много функций, которые предлагает нам пакет.
Примечание о FieldArrays
Еще один удобный объект Formik - the <FieldArray />
.
Объект <FieldArray />
помогает нам управлять формами, которые принимают повторяющийся список входных данных с общим предметом.
Этот метод позволит нам перебирать диапазон значений и создавать поля для каждого из них. У нас также есть доступ к объекту Formik arrayHelpers
, который мы можем использовать для добавления и удаления элементов в массиве полей, которым мы управляем. Эта функция становится очень полезной, когда у вас есть список вещей, которые нужно настроить, например, теги сообщения или список атрибутов продукта и т. Д.
Понимание того, что мы обсуждали в этой статье, является предварительным условием для использования FieldArrays. Когда будете готовы, погрузитесь в мою статью о Field Array:
React Formik: погружение в массивы полей
Давайте взглянем на‹ FieldArray / ›объект Formik medium.com
Кроме того, чтобы узнать о withFormik
и использовании HOC в пакете, прочтите мою статью о том, как его использовать и почему:
Подведение итогов
Также стоит упомянуть, что Formik находится в стадии активной разработки, поэтому обязательно обращайтесь к документации за обновлениями, обзор которых находится по следующему URL-адресу:
Я включил суть нашего примера формы, описанной выше, чтобы действовать как вход в Formik. Не стесняйтесь копировать его в свои проекты, чтобы начать создавать свои собственные формы Formik: