Операции с формами всегда были громоздкой вещью в React. Использование formik может значительно упростить операции с формами.
Build forms in React, without the tears 😭
Введение формика
Прежде чем представить formik, давайте поговорим о некоторых болевых точках в ежедневной работе с бланками.
Когда мы хотим получить доступ к значению элемента управления вводом в форме, обычно есть две операции, одна из которых — использоватьrefЧтобы получить структуру dom, второйиспользовать состояние для хранения значения. Прежде всего, для первого случая, хотя использование ref позволяет нам легко получить узел dom, а затем получить значение ввода, следует отметить, что при использовании React нам нужно всегда говорить себе, а не чтобы напрямую управлять домом! Не манипулируйте домом напрямую! Не манипулируйте домом напрямую! Официал также не рекомендует этот подход, для второго подхода, хотя это официально рекомендуемый подход, потому что состояние было привязано в то время, элементы управления в форме формы также стали управляемыми компонентами.Если мы хотим действительно изменить его данные , нам часто нужно привязать другое событие onChange.Когда элементов управления слишком много, операция также очень громоздка.
Появление formik упрощает работу с формой и делает работу с формой очень простой. Formik не только обеспечивает управление состоянием целевых форм, но и легко проверяет правила форм. На самом деле принцип formik очень прост: в него встроены операции управления состоянием для форм, поэтому нам не нужно отдельно создавать состояние для формы, и использовать его одновременно.Context, что позволяет вкладывать компоненты формы в несколько слоев, и нам больше не нужно передавать их слой за слоем.
Пример начала работы
Давайте рассмотрим простой пример, чтобы увидеть, как используется formik и как он упрощает работу с формами.
В качестве примера возьмем эту форму.Форма содержит три поля: имя, пол, возраст и кнопка отправки.Данные правила формы следующие:
- Имя: Обязательное и не пустое
- пол (пол): обязательный и не пустой
- Age (возраст): обязательно, не пусто, целое число больше 0
формик предоставляетFormik
Компоненты включают в себя initialValues, validate, onSubmit, render и другие реквизиты (не ограничиваясь этим, перечислены только ключевые реквизиты, используемые в настоящее время, полная структура подробно объясняетсяFormik API, следующее объясняет роль каждой опоры:
- initialValues: данные для инициализации формы
- validate: проверка правила формы, возвращает объект сообщения об ошибке
- onSubmit: Получите каждое поле формы и настройте свои собственные бизнес-операции
- render: дочерний компонент внутри формы
Для внутренней формы метод рендеринга будет передавать свойства, свойства включают значения, ошибки, handleSubmit, handleChange, handleBlur и другие свойства (подробнее см.полный реквизит,в:
- значения: соответствует данным формы
- ошибки: информация об ошибке, возвращаемая валидацией после проверки формы
- коснулся: указывает, были ли изменены элементы управления в форме
- handleSubmit: это событие обработки formik для процесса отправки после того, как форма запускает событие отправки, и в нем находится проверка правила.
- handleChane: событие, изменяющее данные формы
- handleBlur: Событие операции после того, как элемент управления потеряет фокус, будет осуществляться процесс проверки правил формы
Пример кода выглядит следующим образом:
<Formik
initialValues={{
name: "",
gender: "",
age: ""
}}
validate={values => {
let errors = {};
if (values.name.length === 0) {
errors.name = "Name can not be empty"
}
if (values.gender.length === 0) {
errors.gender = "You must choose a gender"
}
if (values.age <= 0 || values.age % 1 !== 0) {
errors.age = "Age must be a Positive Integer"
}
return errors;
}}
onSubmit={(values) => {
console.log(values)
}}
render={props =>
<form onSubmit={props.handleSubmit}>
<div className="content">
<div>
<label>姓名: </label><input type="text" id="name" name="name" value={props.values.name}
onChange={props.handleChange} onBlur={props.handleBlur}/>
{props.touched.name && props.errors.name && <div>{props.errors.name}</div>}
</div>
<div>
<label>性别: </label>
<input type="radio" id="male" value="male" name="gender" onChange={props.handleChange}
onBlur={props.handleBlur}/> <label htmlFor="male">男</label>
<input type="radio" id="female" value="female" name="gender" onChange={props.handleChange}
onBlur={props.handleBlur}/> <label htmlFor="female">女</label>
{props.touched.gender && props.errors.gender && <div>{props.errors.gender}</div>}
</div>
<div>
<label>年龄: </label><input type="number" id="age" name="age" value={props.values.age}
onChange={props.handleChange} onBlur={props.handleBlur}/>
{props.touched.age && props.errors.age && <div>{props.errors.age}</div>}
</div>
<div className="submit-area">
<button type="submit">提交</button>
</div>
</div>
</form>
}
/>
Примечание. При выводе сообщений об ошибках обычно
touched.name&&errors.name
Это связано с тем, что когда formik выполняет проверку формы, он проверяет все поля, независимо от того, выполнил ли пользователь какую-либо операцию, но для пользователя обычно не ожидается отображения строки информации об ошибке в поле, которое не было работает, поэтому поле, к которому прикоснулись, необходимо проверить, чтобы увидеть, было ли поле обработано, и оно отображается только после того, как операция была выполнена и возникла ошибка.
Из примера видно, что начальные поля, правила валидации и события отправки передаются через компонент Formik, а после связывания в форме таких событий, как handleSubmit, handleChange и handleBlur, мы можем реализовать простую операцию формы.
Но мы по-прежнему можем видеть, что такие события, как onChange, onBlur и т. д., многократно связаны в каждом элементе управления вводом, и путь каждого сообщения об ошибке ввода очень повторяется, что немного громоздко. К счастью, для сокращения повторяющейся работы formik отправляет упакованные компоненты, такие как Form, Field, ErrorMessage и т. д. Код выглядит следующим образом:
<Formik
......
//same as before
render={props =>
<Form>
<div className="content">
<div>
<label>姓名: </label><Field name="name"/>
<ErrorMessage name="name"/>
</div>
<div>
<label>性别: </label>
<Field name="gender" render={({field}) =>
<input type="radio" name={field.name} value="male" checked={field.value === "male"}
onChange={field.onChange}
onBlur={field.onBlur}/>
}/>
<label htmlFor="male">男</label>
<Field name="gender" render={({field}) =>
<input type="radio" name={field.name} value="female" checked={field.value === "female"}
onChange={field.onChange}
onBlur={field.onBlur}/>
}/> <label htmlFor="female">女</label>
<ErrorMessage name="gender"/>
</div>
<div>
<label>年龄: </label><Field name="age"/>
<ErrorMessage name="age"/>
</div>
<div className="submit-area">
<button type="submit">提交</button>
</div>
</div>
</Form>
}
/>
Видно, что использование компонентов, предоставляемых formik, может еще больше упростить код.При сравнении видно, что компонент Form думает о добавлении onSubmit в форму, компонент ErrorMessage оборачивает ряд суждений, таких как касание и ошибки; Компонент Field инкапсулирован в OnChange, onBlur, value и другие атрибуты, следует отметить, что для радио, флажка, выбора и других элементов управления необходимо выполнить некоторую специальную обработку, обычно используют свой метод рендеринга для настройки, кроме того, из-за рендеринга Метод make Field также может хорошо сочетаться с другими сторонними пакетными элементами управления.
Кроме того, formik также имеет хорошую поддержку атрибутов типа массива.Теперь давайте добавим поле в форму.Стиль формы выглядит следующим образом:
Мы добавили в форму поле адресов, которое представляет собой данные, в которых хранятся адреса, и его правило проверки должно иметь хотя бы одно ненулевое поле.
formik предоставляет компонент FieldArray для работы с полями типа массива Код выглядит следующим образом:
<Formik
initialValues={{
name: "",
gender: "",
age: "",
addresses: [""]
}}
validate={values => {
let errors = {};
if (values.name.length === 0) {
errors.name = "Name can not be empty"
}
if (values.gender.length === 0) {
errors.gender = "You must choose a gender"
}
if (values.age <= 0 || values.age % 1 !== 0) {
errors.age = "Age must be a Positive Integer"
}
let addresses = values.addresses.filter(address => address.trim() !== "");
if (addresses.length === 0) {
errors.addresses = "Addresses must have 1 address at least"
}
return errors;
}}
onSubmit={(values) => {
console.log(values)
}}
render={props =>
<Form>
<div className="content">
......
// same as before
<div>
<label>地址: </label>
<FieldArray name="addresses" render={arrayHelper =>
<div>
{props.values.addresses.map((address, index) =>
<div className="address">
<Field name={`addresses.${index}`}/>
<div className="address_add" onClick={() => {
arrayHelper.push("")
}}>+
</div>
</div>
)}
</div>
}/>
<ErrorMessage name="addresses" component="div" className="error"/>
</div>
<div className="submit-area">
<button type="submit">提交</button>
</div>
</div>
</Form>
}
/>
Видно, что при использовании FieldArray он будет предоставлять параметр arrayHelper, и мы можем легко манипулировать массивом массивов через arrayHelper, например push, pop и т. д. (подробнее см.Полный API-интерфейс arrayHelper)
Пока что это введение основных функций формика.
Вводить
Хотя formik значительно облегчил работу с формами, мы все еще можем видеть, что при проверке формы написанный код все еще относительно громоздкий.В настоящее время требуется появление yup, а опыт yup заключается в проверке правил. И умный автор formik сделал так, чтобы он хорошо поддерживал вас, когда он разработал formik.
Официальное введение yup:
Yup is a JavaScript object schema validator and object parser.
В компоненте Formik есть реквизит под названием validationSchema, который представляет собой интерфейс, зарезервированный для yup. Без лишних слов, давайте сначала покажем код:
//没有yup的情况
<Formik
validate={values => {
let errors = {};
if (values.name.length === 0) {
errors.name = "Name can not be empty"
}
if (values.gender.length === 0) {
errors.gender = "You must choose a gender"
}
if (values.age <= 0 || values.age % 1 !== 0) {
errors.age = "Age must be a Positive Integer"
}
let addresses = values.addresses.filter(address => address.trim() !== "");
if (addresses.length === 0) {
errors.addresses = "Addresses must have 1 address at least"
}
return errors;
}}
//......
/>
//使用yup的情况
<Formik
validationSchema={Yup.object().shape({
name: Yup.string().trim().required("Name can not be empty"),
gender: Yup.string().required("You must choose a gender"),
age: Yup.number().moreThan(0, "Age must be greater than 0").integer("Age must be a integer"),
addresses: Yup.array().compact().min(1, "Addresses must have 1 address at least")
})}
//......
/>
Видно, что после использования Yup делается много представлений с точки зрения размера кода и читабельности, особенно когда форма очень сложная, оптимизация между ними будет очень очевидной.
Видно, что работа Yup очень семантическая, поэтому затраты на обучение очень низкие, нужно только знать его api, пользоваться им легко, так что повторения использования Yup не будет, подробнее см.Документация.
Эпилог
Эта статья является лишь кратким введением в formik+yup, и это только руководство. На самом деле их величие не только здесь, каждый может исследовать их в свое удовольствие. Если вы хотите просмотреть исходный код, нажмитессылка на код формы
Если у вас есть замечания и предложения по данной статье, добро пожаловать к обсуждению и исправлению! ! !