Form operations in React have always been tedious. Formik can greatly simplify form operations. Formik’s slogan is Build Forms in React, without the tears ðŸ˜
Formik introduction
Before we get to FormIK, let’s talk about some of the pain points of manipulating forms on a daily basis.
When we want to access the value of an input control in a form, we usually do two things: we use ref to get the DOM structure, and we use state to store the value. In the first case, it is easy to use ref to get the DOM node and then the input value. However, when using React, we should always tell ourselves not to manipulate the DOM directly. Don’t manipulate dom directly! Don’t manipulate dom directly! It’s not officially recommended; The second option, although officially recommended, is that the controls in the form become controlled components because they are bound to state. If we want to actually change their data, we often need to bind another onChange event, which is tedious when there are too many controls.
Formik, however, simplifies form operations and makes them much simpler. Formik not only provides state management for specific forms, but also makes it easy to verify rules on forms. Formik’s principle is simple: formIK’s built-in state management eliminates the need to create a separate state for the form, and uses the Context to create multiple layers of form components that don’t need to be passed around.
Introductory example
Let’s take a look at a simple example of how formIK is used and how it simplifies forms.
As an example, the form contains three fields, name, gender and age, and a submit button. The given form rules are as follows:
- Name: This parameter is mandatory
- Gender: This parameter is mandatory
- Age: a non-empty integer greater than 0
Formik provides a component named FormIK, which contains the initialValues, validate,onSubmit,render, and other props. Here is a description of each prop:
- InitialValues: Initializes the data of the form
- Validate: Validates a form rule and returns an object with an error message
- OnSubmit: Get the fields of the form and customize your own business operations
- Render: The children component inside the form
For the internal form, the render method passes in a props, which includes values, errors, handleSubmit, handleChange, and handleBlur. (For more details, see the complete props, where:
- Values: indicates the data in the form
- Errors: validates the returned form verification error information
- Touched: Indicates whether the control in the form has been manipulated
- HandleSubmit: FormIK handles the submission process after the form triggers the submission event, where rule verification is included
- HandleChane: An event that changes form data
- HandleBlur: The action event that occurs after a control loses focus, and the process of validating rules on a form
Example code is as follows:
<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>Name:</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>Gender:</label>
<input type="radio" id="male" value="male" name="gender" onChange={props.handleChange}
onBlur={props.handleBlur}/> <label htmlFor="male">male</label>
<input type="radio" id="female" value="female" name="gender" onChange={props.handleChange}
onBlur={props.handleBlur}/> <label htmlFor="female">female</label>
{props.touched.gender && props.errors.gender && <div>{props.errors.gender}</div>}
</div>
<div>
<label>Age:</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">submit</button>
</div>
</div>
</form>} / >Copy the code
Note: This is because formIK checks all fields in the form for errors, regardless of whether the user has performed an operation. Users usually do not want to display an error message in a field that has not yet been performed. The “touched” field is required to check whether the field has already been operated. If the field has been operated and an error occurs, the “touched” field will be displayed.
As you can see from the example, the Formik component passes in the initial field, validates the rule, and submits the event; By binding handleSubmit, handleChange, handleBlur and other events to the form, we can implement a simple form operation.
However, we can still see that in each input control, there are repeated binding events such as onChange, onBlur, and each input error message is very repeated, which seems to be a bit cumbersome. Formik, however, submits wrapped components such as forms, fields, and errorMessages to reduce repetitive work:
<Formik
......
//same as before
render={props= >
<Form>
<div className="content">
<div>
<label>Name:</label><Field name="name"/>
<ErrorMessage name="name"/>
</div>
<div>
<label>Gender:</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">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">female</label>
<ErrorMessage name="gender"/>
</div>
<div>
<label>Age:</label><Field name="age"/>
<ErrorMessage name="age"/>
</div>
<div className="submit-area">
<button type="submit">submit</button>
</div>
</div>
</Form>} / >Copy the code
As you can see, using the component provided by FormIK can simplify the code even further. As you can see from the comparison, the Form component wants to add onSubmit to Form. The ErrorMessage component encloses the touched,errors and other judgments. The Field component encapsulates onChange, onBlur, value and other attributes. It should be noted that radio, checkbox, Select and other controls need to do some special processing separately, usually using the render method to define, in addition, because of the render method, Field can also be well combined with other third party encapsulated controls.
Formik also has good support for array type properties. Now let’s add a field to the form. The form looks like this:
We added a addresses field to the form, which is a piece of data that stores addresses and whose validation rule is that there is at least one non-empty field.
Formik provides a FieldArray component that deals specifically with array type fields, with the following code:
<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>Address:</label>
<FieldArray name="addresses" render={arrayHelper= >
<div>
{props.values.addresses.map((address, index) =>
<div className="address">
<Field name={`addresses.The ${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">submit</button>
</div>
</div>
</Form>} / >Copy the code
As you can see, when FieldArray is used, it provides an arrayHelper argument that makes it easy to manipulate arrays of arrays, such as push, POP, and so on (see the full arrayHelper API for more details).
This concludes the basic functionality of Formik.
Injection Yup
Although FormIK has greatly facilitated the manipulation of forms, we can still see that forms validation requires a lot of code, which requires YUP, whose specialty is rule verification. And smart formIK writers designed FormIK to support YUP.
Yup is a JavaScript Object Schema Validator and Object Parser.
In the Formik component there is a prop called validationSchema, which is the interface reserved for yup. Without further ado, show code first:
// There is no 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;
}}
/ /...
/>
// Use yup
<Formik
validationSchema={Yup.object().shape({
name: Yup.string(a).trim(a).required("Name can not be empty"),
gender: Yup.string(a).required("You must choose a gender"),
age: Yup.number(a).moreThan(0,"Age must be greater than 0").integer("Age must be a integer"),
addresses: Yup.array(a).compact(a).min(1,"Addresses must have 1 address at least/ / ")})}.
/>
Copy the code
As you can see with Yup, there is a lot of submission, both in terms of code volume and readability, especially if the form is very complex, the optimization can be very obvious.
As you can see, the operation of Yup is very semantic, so the learning cost is very low. You only need to know its API, so you can use it easily, so there is no need to repeat the use of Yup, see the Yup documentation for details.
conclusion
This article is just a simple introduction to FormIK + YUP. In fact, their formidable place is not only this, we can enjoy the exploration. To view the source code click the form code link
If you have any comments or suggestions on this article, welcome to discuss and correct!!