21
Creating forms with Formik in React
Forms are an important medium to collect user's information which helps us to deliver better features in the future of the application. In this article we will learn about formik. Why do we need it? What problems it solves? The different features and options available in it that makes our work more easy and manageable.
In general, to create a form we make use of the most basic html input tag which primarily consists of input fields such as text-areas, checkboxes, radio-buttons, select-options, etc.
We can create a form in javascript using these basic input types available. For example, take a look at the basic login form shown in the below image:
When we talk about doing this in react, we can follow this approach but it seems to be an old-school way and not the react way!
Let's create a simple login form in react with two fields, email and password.
We can make use of local state and can capture the input by calling onChange or other event function depending on the input we are using, and can use the information as required.
Refer to the below following example:
This form seems quite easy as it has only two fields to handle.
But as our fields starts to add up, and our form starts to grow, it becomes bit complex, as declaring states for each field, handling the event functions for each of them, and in that too if we have to handle validations, it will be very difficult to manage(for those who have experienced such a problem, definitely know the pain of managing each and every field state in a form). So what should we do to handle huge forms while handling the validations and not compromising the user's crucial information? Answer to this question is to use Formik. Yes, this is where formik acts like a life saviour.
Formik is a library which helps us to handle complex forms without worrying about the form state. It basically helps us with the 3 most annoying parts involved with a form:
- Getting values in and out of form state
- Validation and error messages
- Handling form submission
The main idea behind Formik is to create a scalable, performant, form helper with a minimal API that does the really really annoying stuff, and leaves the rest up to us.
npm install formik --save
yarn add formik
Simply add the following <script>
tag to the bottom of your HTML file.
<script src="https://unpkg.com/formik/dist/formik.umd.production.min.js"></script>
Formik generally provides some functions to handle events at form level like handleChange, handleBlur, and handleSubmit. We can add these functions to our form via props.
Let's check the most basic example of how to use Formik:
See how we replaced the html <input>
with formik's <Field>
tag. It provides more flexibility to customise the input fields along with existing features of formik.
<Field />
automatically hook up the inputs to Formik. It uses the name attribute to match up with Formik state. <Field />
will default to an HTML <input />
element.
We basically wrap the Form inside the Formik tag. It uses a render props pattern, which then handles the form state separately from our component's state.
It gives us lot of useful props like values, errors, setFieldValue, setFieldTouched, etc. Values prop is the most commonly used prop to fetch out the current form state value at any point, similarly errors provide us with an array/object which will contain field name and the required error message which we want to display to the user for better user experience.
As you can see we have a validate function inside Formik.
It accepts either a synchronous or asynchronous function, where we can actually define a set of rules for our form values, defining what values are acceptable or are mandatory for the user to fill. So using validate, it's upto us what validations we want to add.
Also, if we have a lot of validations in our form, we can use a third party library like Yup. In fact, formik has a special config option/prop for Yup object schemas called validationSchema which will automatically transform Yup's validation errors into a pretty object whose keys match values and touched. This symmetry makes it easy to manage business logic around error messages.
So either we can use the validate function of Formik or Yup's validationSchema depending upon the expectations.
Example of validating email and password:
When we deal with the real-life projects we end up handling complex objects or arrays as data type but worry not formik also provides support for arrays and nested objects.
Formik provides us with <FieldArray>
component which helps us in dealing with array/list operations. We can pass a property in name
with the relevant path of the key in the array we want to deal.
We can then use the inbuilt methods like push, swap, move, insert, unshift, remove, pop, replace, provided by arrayHelpers for performing the basic calculations like adding, removing first/last element in an array, etc.
Here are some example :
Consider the address
field which we initialised as an empty array. We have the ability to add address values using Add
button. On click of the button, it calls arrayHelpers.push()
method which takes in the value and adds it in the array defined in the name props of FieldArray
.
Similarly, for removing any address, we are calling arrayHelpers.remove()
, which takes in an index, and removes that particular item from the array.
So, we don't have to care about spreading the array and then assigning it again and stuff like that.
It makes very easy and simple to deal the arrays/objects.
So far we discussed about installing, validating stuff, working with arrays, which leaves us with the final step of the form cycle i.e, form submission.
To be precise, when we submit a form, it calls the onSubmit method of formik.
There are a couple of steps followed before the final submission like:
Pre-Submit: In this step, it touches all the fields once, incrementing submitCount=+1 and also checks for initialValues, which are required and should be specified(preferable).
-
Validate: Here it checks all field-level validations, validate function, and validationSchema asynchronously and deeply merge results.
- In case of any errors it simply aborts the submission, setting isValidating to false, set errors, set isSubmitting to false.
- If no errors are found then it completes the submission
Submission: It starts by calling your submit-handler (onSubmit/handleSubmit), and sets isSubmitting to false, completing the form cycle.
Example showing isSubmitting, isValidating values:
Basically, what is happening here is when we click on submit button, it first checks for the initial values, then calls the validate function.
In this case, as email and password fields are required, we are setting error object with some message we want to display.
As soon as user clicks on-submit button, the error message pops up, letting the user know which fields are mandatory to fill. Thus, it makes easier for us to deal with forms and validation, thereby, giving a better user experience.
Summing up, all we talked about was, the overview of formik, how it works, how it helps us in dealing with the messy operations involved in while dealing with a form, and how it lets us to focus on what's important, handling all the tedious work itself.
Similar to formik there are other libraries as well, would really like to try out the alternate options available, but for now this was all I knew.
Hope this article helped you in understanding the basics of formik. This piece of information only explains a very little part of what features and options we can avail but there is a lot more in it.
You can read the Formik documentation for more understanding.
Thank you for your patience.
Happy Coding :)
21