DEV Community

Cover image for Building React Forms Painlessly With Formik
J0shcodes
J0shcodes

Posted on

Building React Forms Painlessly With Formik

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

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)