July 4, 2022

Blog @ Munaf Sheikh

Latest news from tech-feeds around the world.

Formik Vs React Hook Form

Great post from our friends at Source link

Forms are the most common interactive tool we can encounter in many applications and also the challenging part to collect and preserve the data. There are multiple libraries that we can use such as React Final Form, Formik, Redux Form, and React Hook Form. In this article, we will focus on how React can solve the problem of working with forms, and we will discuss two well-known libraries called React Hook Form and Formik.

React Components

Firstly, I would like to explain the difference between the controlled and uncontrolled components. The HTML elements <input> and <select> differ from the other DOM elements by having their proper internal state. React’s official page recommends giving the control of changing the value of these form elements to the library itself since in React there is the principle of “the state is the single source of truth.” In this way, the components which have their states managed by React are called “controlled components.” On the other hand in the official page, also mentions that we may use uncontrolled components: like writing an event handler and piping all of the input state through a React component.

Uncontrolled components are like traditional HTML form inputs, “ref” is used to get the form values and is simpler to implement form inputs. In controlled components, every time the user changes the input value, the form is also updated and it saves the data in its state. This feature can be useful when we want to do in-place validation and force a specific input format.

Formik vs React Hook Form

According to React documentation, Formik is a good fit if we want a complete solution including validation, keeping track of visited fields, and handling form submission. Formik uses controlled components. Also, since we can keep the form state localized and managed by Formik, it is good for building multi-step forms.

On the other hand, React Hook Form uses uncontrolled components. Since uncontrolled components keep the source of truth in the DOM, it is easier to integrate React and non-React code. React Hook Form isolates input components from the others and it avoids this unnecessary re-rendering. So it is a great advantage in terms of the performance compared to Formik which updates every change in every input field. 

In Formik, you can build forms in two different ways: one, by using a Formik component and Formik-provided fields; second, by using the useFormik hook. With the first method, it enables all features and this could harm the potential of Formik. For simple forms, it is recommended to use useFormik hook. With useFormik we cannot work with components like <Field>, <FastField>, <ErrorMessage>, and connect() because they require React Context.

In our example, we will create a multistep form with the Formik component and React Hook Form. In the first example with Formik library, we wrap our steps inside of Formik component:

<Formik
       initialValues={
        {firstName: '',
         lastName:'',
         email:'',
         age: '',
         birthday: '',
         companyName: '',
         companyYear: ''}
       }
       validationSchema={currentValidationSchema}
       enableReinitialize
       onSubmit={handleSubmitFormik}
     >
       {({ isSubmitting, handleChange, values }) => (
         <Form className="App">
             <div className="App”>
             {renderStepFormik(activeStep, handleChange, values)}
             {activeStep===3 ?
               "":
               <button
                 disabled={isSubmitting}
                 className="next"
                 type="submit"
                 color="primary"
               >
                 »
               </button>
             }
           </div>
         </Form>
       )}
     </Formik>

In the first step, we have a first name, last name, and email; in the second: age and birthday; and in the last, one company name and year. Inside of the renderStepFormik function, we have a switch to render every step with its related fields and Form component:

function Form({formData, handleChange, values, register} : FormProps){
 useEffect(() =>console.log("Render times:", renderTimes++));
   return (
   <div className="App">
   <Grid container spacing={3}>
   {formData.map(({id, label, type} : FormData) => {
       return (
         <>
         <Grid item xs={12}>   
         <TextField
           id={id}
           label={label}
           name={id}
           type={type}
           onChange={handleChange}
           value={getIn(values, id)}
         />
         </Grid>
         </>
       );
     })
   }
   </Grid>
   </div>
   );
}

Inside of the useEffect hook, we calculate the times that re-render the Form component. As we can see in the gif below the Form component re-renders 42 times. Let’s compare the same multi-step form with the React Hook Form library.

With React Hook Form, we need to create three components for the three steps. Since React hook form keeps field values in DOM, if we use the same Form component, we see the first step filled values in the second step as prefilled. We use the register function from the library to set the field values to submit.

function Form({formData, register, handleSubmit, step, setStep} : FormProps){
 const onSubmit = (data : Object) => {
   if (step===3) {
     alert(JSON.stringify(data, null, 2));
   }
   setStep(step)
 }
   return (
   <div className="App">
    <form onSubmit={handleSubmit(onSubmit)}>
     <Grid container spacing={3}>
      {formData.map(({id, label, type} : FormData) => {
        return (
         <>
         <Grid item xs={12}>   
         <TextField
           id={id}
           fullWidth
           label={label}
           name={id}
           type={type}
           {...register(id)}
          />
         </Grid>
         </>
       );
     })
    }
    </Grid>
    <button
      className="next"
      type="submit"
      color="primary"
    > »</button>
   </form>
   </div>
   );
}

As we can see below, the component renders three times. Since our source of the truth is DOM with React Hook Form, it doesn’t re-render every time the input changes. This could be great for the performance optimization when we have many fields in a simple form.

Conclusion

To sum up, in our multi-step form example, while React Hook Form prevented the whole form to re-render for a single field change, Formik updated it when there were changes in the input. It is certain that there is less code written with Formik since we render only one component and with React hook form three, but also we should consider that we would have cost on performance because of the re-renders. 

According to the requirements of our application, we should decide which one should be appropriate. Formik can be useful when we want to do in-place validation and give a specific input format. Besides that, since we keep form state localized, it is advantageous for building multi-step forms. React hook form is great for simple forms, and it does not have any dependencies. At the end, both libraries are very useful to implement forms with React.

#Formik #React #Hook #Form