Loading

React - Basic Form building and validation with Formik and Yup

React - Basic Form building and validation with Formik and Yup

In this article, we will learn how to build a basic form with Formik and another library called Yup that allows us to perform validation in very few steps. In React apps, handling and managing forms are not so easy. There are many libraries in the Node Package Manager(NPM). Formik helps us to build forms in a simpler way along with Yup. Before we start, we will go through the basics of Formik and Yup.

Formik

According to the docs, Formik is a small library that helps us 3 things:

  1. Getting values in and out of form state
  2. Validation and error messages
  3. Handling form submission

Yup

Yup is a JavaScript schema builder for value parsing and validation. Explain a schema, convert a value to match, validate the shape of an existing value, or both. Yup schema is extremely powerful and supports modeling complex, interdependent validations, or value transformations.

Next, we will install Formik and Yup packages.

# for npm
npm install formik yup --save

# for yarn
yarn add formik yup

You may also like: Lazy Loading with React Suspense

1. Building form fields and initial values in Formik

I will consider a simple signup form that consists of Name, Email, Password, and Confirm Password fields.

<Form>
  <FormGroup>
    <Col sm={2}>
      <FormLabel>
        Name:
    </FormLabel>
    </Col>
    <Col sm={10}>
      <Field
        type="text"
        name="name"
      />
    </Col>
    <ErrorMessage name="name">{value => <Col sm={10}><small className="text-danger">{value}</small></Col>}</ErrorMessage>
  </FormGroup>
  <FormGroup>
    <Col sm={2}>
      <FormLabel>Email: </FormLabel>
    </Col>
    <Col sm={10}>
      <Field
        type="text"
        name="email"
      />
    </Col>
    <ErrorMessage name="email">{value => <Col sm={10}><small className="text-danger">{value}</small></Col>}</ErrorMessage>
  </FormGroup>
  <FormGroup>
    <Col sm={2}>
      <FormLabel>Password: </FormLabel>
    </Col>
    <Col sm={10}>
      <Field
        type="password"
        name="password"
      />
    </Col>
    <ErrorMessage name="password">{value => <Col sm={10}><small className="text-danger">{value}</small></Col>}</ErrorMessage>
  </FormGroup>
  <FormGroup>
    <Col sm={10}>
      <FormLabel>Confirm Password: </FormLabel>
    </Col>
    <Col sm={10}>
      <Field
        type="password"
        name="confirmPassword"
      />
    </Col>
    <ErrorMessage name="confirmPassword">{value => <Col sm={12}><small className="text-danger">{value}</small></Col>}</ErrorMessage>
  </FormGroup>
  <FormGroup>
    <Col>&nbsp;</Col>
    <Col sm={10}><Button name="submit" type="submit">Submit</Button></Col>
  </FormGroup>
</Form>
const initialValues = {
  name: '',
  email: '',
  password: '',
  confirmPassword: ''
};

The property name declared in the initialValues should match the name of the form fields. You must initialize all fields with initial values otherwise React will throw an error.

2. Creating validation schema with Yup

Setting up form fields are easy, validating the form values are not so easy. You must write many lines of code to validate all the fields. Yup helps us to make form validation much easier. Formik has an option to validate form fields that are called validationSchema. We can pass the Yup validation schema to the validationSchema.

Yup.object({
    name:   Yup.string()
            .min(2,'Name must be at least 2 characters')
            .max(20, 'Name must be at most 20 characters')
            .required('Name can not be empty'),
    email:  Yup.string()
            .email('Enter valid email address')
            .required('Email can not be empty'),
    password: Yup.string()
            .min(6, 'Password must be at least 6 characters')
            .required('Password can not be empty'),
    confirmPassword: Yup.string()
            .oneOf([Yup.ref('password'), null], 'Passwords must match')
            .required('Confirm password can not be empty')
})

As you can see in the above code, the schema is really simple. I have wrapped our four fields in a Yup object then wrote schema for an individual field. For example, we consider the name, must be required that means the value is not empty, has a minimum length of 2 characters, and has a maximum length of 20 characters.

name: Yup.string()
.min(2, "Name must be at least 2 characters")
.max(20, "Name must be at most 20 characters")
.required("Name can not be empty") 

Show error messages are not so tough. The Formik’s validation function runs on each keystroke of user inputs that means error messages will display immediately after the user has typed something in a field. To overcome this problem, I have used touched state which means error will show after the user has done typing.

{errors.name && touched.name ? (
  <p class="error">{errors.name}</p>
) : null}

But, I personally liked Formik's ErrorMessage component which is really handy.

<ErrorMessage name="name">
     {value=> <p class="error">{value}</p>}
</ErrorMessage>

You may also like: Recoil - a new state management library developed by Facebook for React

3. Handling form submission

To submit a form in Formik, you need to use handleSubmit. We can access the submitted values within the onSubmit handler. You can do whatever you want with values if you want to submit these values into your backend as a payload to the API.

<Formik
       initialValues={initialValues}
       validationSchema={validationSchema}
       onSubmit={(values) => {
           setFormValues(JSON.stringify(values));
       }}>
...
</Formik>

Conclusion

I will post different types of form validation using Formik and Yup. If you want to learn more, follow our article, I will talk about more advanced use cases of Formik and Yup in our next article. I hope you have liked this article and learn something new. Feel free to contact us. Thanks for reading.

Github: Complete code reference

Related Articles