Разбиваем 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. Прочтите следующую статью, чтобы понять эти различия и то, как использовать компоненты для создания полезных элементов формы:



Введение в использование элементов формы в React
Компоненты формы React 101: что вам нужно знать medium.com



Ага: анализ и проверка объектов

Хотя это и не обязательно, знание того, как работает 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:



Кроме того, чтобы узнать о withFormik и использовании HOC в пакете, прочтите мою статью о том, как его использовать и почему:



Подведение итогов

Также стоит упомянуть, что Formik находится в стадии активной разработки, поэтому обязательно обращайтесь к документации за обновлениями, обзор которых находится по следующему URL-адресу:



Я включил суть нашего примера формы, описанной выше, чтобы действовать как вход в Formik. Не стесняйтесь копировать его в свои проекты, чтобы начать создавать свои собственные формы Formik: