
Недавно у меня была возможность использовать замечательную библиотеку валидации в большом проекте React, в котором я участвовал.
Те из вас, кто знаком с формами в Интернете, знают, что проверка на стороне клиента является важным аспектом правильной работы с формами. После активного использования нескольких библиотек форм React я недавно остановился на Formik как на библиотеке форм, которую я предпочитаю. Formik привел меня к «да» (благодаря поддержке «из коробки»), который открыл мир эффективной и простой проверки форм на стороне клиента. Ага просто потрясающая своей простотой, скоростью и полнотой. Однако чего-то по-прежнему не хватало ...
Использование файлов конфигурации JSON для создания форм - разумный и логичный шаг к управлению большим приложением на основе форм. Один просто импортирует конфигурацию в компонент контейнера вашей формы, а затем перебирает поля, чтобы отобразить фактические компоненты формы. Эти входные компоненты разделены на отдельные классы / файлы и отображаются средством визуализации компонентов поля, как указано в файлах конфигурации.
Пример файла конфигурации JSON
{ "contact": {
"formname": "contact",
"fields": [
{
"fieldname": "firstname",
"input": "textinput",
"label": "First Name",
"yup":
"type": "string",
"checks": [
{
"key": "minLength",
"val": 2,
"err": "is invalid"
}
]
}
} , {
"fieldname": "email",
"input": "textinput",
"label": "Email Address",
"yup": {
"type": "string",
"checks": [
{
"key": "email",
"val": true,
"err": "is not a valid email"
}
]
}
} , {
"fieldname": "message",
"input": "textareainput",
"label": "Message",
"yup": {
"type": "string",
"checks: [
{
"key": "maxLength",
"val": 100,
"err": "is too long"
}
]
}
}
}
}
Средство визуализации компонента поля
import React from 'react'
import { Field } from 'formik'
import { contact } from 'config' // Above config file
export function switchInput (field) {
let f = { ...field }
switch(f.input) {
case 'TextArea':
f['component'] = TextAreaInput
default:
f['component'] = TextInput
return f
}
class FieldComponents extends React.Component {
renderField = (field, errors) => {
let specific = this.switchInput(field)
let props = {
name: field.name,
label: field.label,
placeholder: field.placeholder ? field.placeholder : '',
type: field.input ? field.input : 'text',
errors
}
return React.createElement(Field, props)
}
render() {
contact.fields.map( field => this.renderField(field, this.form.errors)
}
}
export default FieldComponents
Пример фактического компонента поля выглядит следующим образом
import React from 'react'
import { ErrorMessage } from 'formik'
const Label = ({ error, children, htmlFor, ...props }) => (children) ? <label {...props}>{children}</label> : ''
const TextInput = ({
field: { name, value, ...field },
form: { touched, errors, handleBlur, handleChange },
label,
type,
disabled,
placeholder
}) => {
const error = errors[name]
return (
<div className={`form-group ${name} ${props.classes ? props.classes : ''}`}>
{label &&
<Label htmlFor={name} error={error} className="formlabel">
{label}
</Label>
}
<div>
<input
id={name}
name={name}
type={type}
disabled={disabled}
placeholder={placeholder}
onBlur={handleBlur}
onChange={handleChange}
value={value || ''}
/>
<ErrorMessage component="div" className="error" name={name} />
</div>
</div>
)
}
Собирая все это вместе, мы используем замечательный пакет json-schema-to-yup, созданный Кристианом Мандрупом (в который, ваш покорный слуга, с течением времени были внесены незначительные изменения).
import React from 'react'
import { Formik, Field } from 'formik'
import { buildYup } from 'json-schema-to-yup'
import FieldComponents from 'FieldComponents'
class JSONValidatedForm extends React.Component {
function jsonShape(fields, name) {
const shape = {
title: name,
type: 'object',
log: true,
required: [],
properties: {}
}
const config = { errMessages: {} }
fields.forEach(f => {
let nullable = false
const name = f.verb ? `${f.name}__${f.verb}` : f.name
if (f.edit) {
config.errMessages[name] = {}
if (f.required) {
shape.required.push(name)
config.errMessages[name].required = `${f.label} is required`
config.errMessages[name].string = `${f.label} is required`
} else {
nullable = true
}
if (f.yup && f.yup.type) {
shape.properties[name] = { type: f.yup.type }
f.yup.checks.forEach(check => {
shape.properties[name][check.key] = check.val
if (check.err) { config.errMessages[name][check.key] = check.err }
})
shape.properties[name].nullable = nullable || false
}
}
})
return buildYup(shape, config)
}
render() {
<Formik
validationSchema={this.jsonSchema()}
validateOnChange={true}
validateOnBlur={true}
onSubmit={() => console.log('Submitted')}
render={ (props, actions) => { return ( <FieldComponents ...props /> ) }
/>
}
}
Как видите, в одном поле можно выполнить несколько проверок.
Наша схема JSON не совсем соответствует спецификации, поэтому метод jsonShape преобразовывает ее в форму, ожидаемую json-schema-to-yup, которая анализирует форму и затем предоставляет результат проверки Formik. Это всего лишь пример того, насколько гибким может быть этот стек проверки. Наслаждаться!