Building React Forms Painlessly With Formik
Tags: javascript, react, forms, formik
Published: 2021-11-08 11:46:10

Forms are really important for us as web developers, because on every application you do in real life, you are probably going to need to do forms.


Building forms in React can be tiring and can get messy. If you have a small form with few data inputs you can build it without using a form library. The same can't be said when building forms with larger number of data inputs and validation rules.


In this article, I am going to demonstrate building forms with Formik. I am also going to go into the features Formik provides. This is the screenshot of what we will be building: 

![Image of a web form made with formik](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f7c3l3u446ni19x4u5ui.png)

#Formik Forms

We will start by creating a React application on our local environment. To do this, we open the command line and go to a document folder using:

```
cd documents
```

After that we create our React application and install `bootstrap` to add a little bit of styles to our form by using the classes provided by `bootstrap`.

Run the following commands in the command line:

```
npx create-react-app formik-forms
cd formik-forms
npm install react-bootstrap bootstrap
npm install formik
yarn start
```

The commands above should get us to the point where we have created a new React project, installed pretty much the needed dependencies, and are running the app locally.

After the React project has been created on your computer, open it with your preferred code editor and create a new file called `userForm.js`. Add the following code to the new file created:

```
import React from 'react'
import {Formik} from 'formik'
import 'bootstrap/dist/css/bootstrap.min.css'
```

We will be using functions, functional components, and the following form template I have created already with bootstrap. Since you have installed and imported bootstrap into your React project, you shouldn't have any issues with this. 

So you can copy and paste the template below into your own `userForm.js` file or better still create your own using bootstrap

```
<div className="container">

  <div className="col-md-12 mt-5">
    <form>
      <h4 className="mb-3">Personal information</h4>

      <div className="row">
        <div className="col-md-6 mb-3">
          <label htmlFor="firstname">First name</label>
          <input type="text" className="form-control" id="firstname" name="firstname"/>
        </div>
        <div className="col-md-6 mb-3">
          <label htmlFor="lastname">Last name</label>
          <input type="text" className="form-control" id="lastname" name="lastname"/>
        </div>
      </div>
  
      <div className="mb-3">
        <label htmlFor="email">Email</label>
        <input type="email" className="form-control" id="email" name="email" placeholder="you@example.com"/>
      </div>
      
      <div className="row">
        <div className="col-md-5 mb-3">
          <label htmlFor="country">Country</label>
          <select className="custom-select d-block w-100" id="country" name="country">
            <option value="">Choose...</option>
            <option value="NIG">Nigeria</option>
            <option value="GH">Ghana</option>
            <option value="SA">South Africa</option>
          </select>        
        </div>
        <div className="col-md-4 mb-3">
          <label htmlFor="state">State</label>
          <select className="custom-select d-block w-100" id="state" name="state">
            <option value="">Choose...</option>
            <option value="lagos">Lagos</option>
            <option value="east legion">East Legion</option>
            <option value="cape town">Cape Town</option>
          </select>             
        </div>
        <div className="col-md-3 mb-3">
          <label htmlFor="zip">Zip</label>
          <input type="text" className="form-control" id="zip" name="zip"/>
        </div>
      </div>
  
      <hr className="mb-4"/>
      <button className="btn btn-primary btn-lg btn-block" type="submit">
            Submit
      </button>
      </form>
   </div>

</div>
```

Still in our userForm.js file, I will be wrapping the form components in the `Formik` component we imported earlier, but before that, we will have to declare our `Formik` component and provide a function that gives us props with a lot of method that we will use inside our form.

```
const UserForm = () => {
    return (
      <Formik>
        { ({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit
        }) => (
        ) }
      </Formik>
    )
}
```

In the code above, I have de-structured the various methods we need from the props, this will make it easier for us to use as properties in our form. For example, we can now do `values`, instead of `props.values`. 

The next thing to do is to return some JSX or in this case our `form` components in the `Formik` function.

```
const UserForm = () => {
    return (
      <Formik>
        { ({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit
        }) => (
        <div className="container">

          <div className="col-md-12 mt-5">
            <form>
              <h4 className="mb-3">Personal information</h4>

              <div className="row">
                <div className="col-md-6 mb-3">
                  <label htmlFor="firstname">First name</label>
                  <input type="text" className="form-control" id="firstname" name="firstname"/>
                </div>
                <div className="col-md-6 mb-3">
                  <label htmlFor="lastname">Last name</label>
                  <input type="text" className="form-control" id="lastname" name="lastname"/>
                </div>
              </div>
  
              <div className="mb-3">
                <label htmlFor="email">Email</label>
                <input type="email" className="form-control" id="email" name="email" placeholder="you@example.com"/>
              </div>
      
              <div className="row">
                <div className="col-md-5 mb-3">
                  <label htmlFor="country">Country</label>
                  <select className="custom-select d-block w-100" id="country" name="country">
                    <option value="">Choose...</option>
                    <option value="NIG">Nigeria</option>
                    <option value="GH">Ghana</option>
                    <option value="SA">South Africa</option>
                  </select>        
                </div>
                <div className="col-md-4 mb-3">
                  <label htmlFor="state">State</label>
                  <select className="custom-select d-block w-100" id="state" name="state">
                    <option value="">Choose...</option>
                    <option value="lagos">Lagos</option>
                    <option value="east legion">East Legion</option>
                    <option value="cape town">Cape Town</option>
                  </select>             
                </div>
                <div className="col-md-3 mb-3">
                  <label htmlFor="zip">Zip</label>
                  <input type="text" className="form-control" id="zip" name="zip"/>
                </div>
              </div>
  
              <hr className="mb-4"/>
              <button className="btn btn-primary btn-lg btn-block" type="submit">
            Submit
             </button>
           </form>
         </div>

       </div>
        ) }
      </Formik>
    )
}
```  

Now the `Formik` component requires properties. One a property that helps formik to know what we are going to be using on the form i.e the values that `Formik` component will be controlling and another property that controls the submission of the form when a submit button is clicked.

```
const UserForm = () => {
    return (
      <Formik
        initialValues={{
          firstname: ''
          lastname: ''
          email: ''
          country: ''
          state: ''
          zip: '' 
        }}
        onSubmit={() => {
         console.log('form submitted')
        }}
      >
        { ({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit
        }) => (
        <div className="container">

          <div className="col-md-12 mt-5">
            <form>
              <h4 className="mb-3">Personal information</h4>

              <div className="row">
                <div className="col-md-6 mb-3">
                  <label htmlFor="firstname">First name</label>
                  <input type="text" className="form-control" id="firstname" name="firstname"/>
                </div>
                <div className="col-md-6 mb-3">
                  <label htmlFor="lastname">Last name</label>
                  <input type="text" className="form-control" id="lastname" name="lastname"/>
                </div>
              </div>
  
              <div className="mb-3">
                <label htmlFor="email">Email</label>
                <input type="email" className="form-control" id="email" name="email" placeholder="you@example.com"/>
              </div>
      
              <div className="row">
                <div className="col-md-5 mb-3">
                  <label htmlFor="country">Country</label>
                  <select className="custom-select d-block w-100" id="country" name="country">
                    <option value="">Choose...</option>
                    <option value="NIG">Nigeria</option>
                    <option value="GH">Ghana</option>
                    <option value="SA">South Africa</option>
                  </select>        
                </div>
                <div className="col-md-4 mb-3">
                  <label htmlFor="state">State</label>
                  <select className="custom-select d-block w-100" id="state" name="state">
                    <option value="">Choose...</option>
                    <option value="lagos">Lagos</option>
                    <option value="east legion">East Legion</option>
                    <option value="cape town">Cape Town</option>
                  </select>             
                </div>
                <div className="col-md-3 mb-3">
                  <label htmlFor="zip">Zip</label>
                  <input type="text" className="form-control" id="zip" name="zip"/>
                </div>
              </div>
  
              <hr className="mb-4"/>
              <button className="btn btn-primary btn-lg btn-block" type="submit">
            Submit
             </button>
           </form>
         </div>

       </div>
        ) }
      </Formik>
    )
}
```
In the `form` component, you will notice all input components has an `id`. It is these `id` values that we use as the keys in the `initialValues` object. For the form submission, I will just be displaying a string in the browser's console `console.log('form submitted')` since we are not working with a server or database in this article.

We will need to link the `initialValues` property to the actual input we will be getting from our form by adding a `value` property to the `input` components and accessing users input from the `values` method.

```
const UserForm = () => {
    return (
      <Formik
        initialValues={{
          firstname: ''
          lastname: ''
          email: ''
          country: ''
          state: ''
          zip: '' 
        }}
        onSubmit={() => {
         console.log('form submitted')
        }}
      >
        { ({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit
        }) => (
        <div className="container">

          <div className="col-md-12 mt-5">
            <form>
              <h4 className="mb-3">Personal information</h4>

              <div className="row">
                <div className="col-md-6 mb-3">
                  <label htmlFor="firstname">First name</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="firstname" 
                    name="firstname" 
                    value={values.firstname}
                  />
                </div>
                <div className="col-md-6 mb-3">
                  <label htmlFor="lastname">Last name</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="lastname" 
                    name="lastname" 
                    value={values.lastname}
                  />
                </div>
              </div>
  
              <div className="mb-3">
                <label htmlFor="email">Email</label>
                <input 
                  type="email" 
                  className="form-control" 
                  id="email" 
                  name="email" 
                  placeholder="you@example.com" 
                  value={values.email}
                />
              </div>
      
              <div className="row">
                <div className="col-md-5 mb-3">
                  <label htmlFor="country">Country</label>
                  <select 
                    className="custom-select d-block w-100" 
                    id="country" 
                    name="country" 
                    value={values.country}
                  >
                    <option value="">Choose...</option>
                    <option value="NIG">Nigeria</option>
                    <option value="GH">Ghana</option>
                    <option value="SA">South Africa</option>
                  </select>        
                </div>
                <div className="col-md-4 mb-3">
                  <label htmlFor="state">State</label>
                  <select 
                    className="custom-select d-block w-100" 
                    id="state" 
                    name="state" 
                    value={values.state}
                  >
                    <option value="">Choose...</option>
                    <option value="lagos">Lagos</option>
                    <option value="east legion">East Legion</option>
                    <option value="cape town">Cape Town</option>
                  </select>             
                </div>
                <div className="col-md-3 mb-3">
                  <label htmlFor="zip">Zip</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="zip" 
                    name="zip" 
                    value={values.zip}
                  />
                </div>
              </div>
  
              <hr className="mb-4"/>
              <button className="btn btn-primary btn-lg btn-block" type="submit">
            Submit
             </button>
           </form>
         </div>

       </div>
        ) }
      </Formik>
    )
}
``` 
 Finally we will need to add an `onSubmit` property to our `form` component and pass in the `handleSubmit` method from the `Formik` component, and also add an `onChange` property to the input components and pass in the `handleChange` method. 

```
const UserForm = () => {
    return (
      <Formik
        initialValues={{
          firstname: ''
          lastname: ''
          email: ''
          country: ''
          state: ''
          zip: '' 
        }}
        onSubmit={() => {
         console.log('form submitted')
        }}
      >
        { ({
          values,
          errors,
          touched,
          handleChange,
          handleBlur,
          handleSubmit
        }) => (
        <div className="container">

          <div className="col-md-12 mt-5">
            <form onSubmit={handleSubmit}>
              <h4 className="mb-3">Personal information</h4>

              <div className="row">
                <div className="col-md-6 mb-3">
                  <label htmlFor="firstname">First name</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="firstname" 
                    name="firstname" 
                    value={values.firstname}
                  />
                </div>
                <div className="col-md-6 mb-3">
                  <label htmlFor="lastname">Last name</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="lastname" 
                    name="lastname" 
                    value={values.lastname}
                  />
                </div>
              </div>
  
              <div className="mb-3">
                <label htmlFor="email">Email</label>
                <input 
                  type="email" 
                  className="form-control" 
                  id="email" 
                  name="email" 
                  placeholder="you@example.com" 
                  value={values.email}
                />
              </div>
      
              <div className="row">
                <div className="col-md-5 mb-3">
                  <label htmlFor="country">Country</label>
                  <select 
                    className="custom-select d-block w-100" 
                    id="country" 
                    name="country" 
                    value={values.country}
                  >
                    <option value="">Choose...</option>
                    <option value="NIG">Nigeria</option>
                    <option value="GH">Ghana</option>
                    <option value="SA">South Africa</option>
                  </select>        
                </div>
                <div className="col-md-4 mb-3">
                  <label htmlFor="state">State</label>
                  <select 
                    className="custom-select d-block w-100" 
                    id="state" 
                    name="state" 
                    value={values.state}
                  >
                    <option value="">Choose...</option>
                    <option value="lagos">Lagos</option>
                    <option value="east legion">East Legion</option>
                    <option value="cape town">Cape Town</option>
                  </select>             
                </div>
                <div className="col-md-3 mb-3">
                  <label htmlFor="zip">Zip</label>
                  <input 
                    type="text" 
                    className="form-control" 
                    id="zip" 
                    name="zip" 
                    value={values.zip}
                  />
                </div>
              </div>
  
              <hr className="mb-4"/>
              <button className="btn btn-primary btn-lg btn-block" type="submit">
            Submit
             </button>
           </form>
         </div>

       </div>
        ) }
      </Formik>
    )
}
```

In my next article, which will be a sequel to this one, I will be expanding on the form we created here by doing some form validation with **Yup** a library used for easy form validation.

Well that does it for this article. I hope you do find article useful.

Thanks and have a nice read.