React Form validations using Formik
Tags: react, javascript, webdev
Published: 2020-06-08 02:48:55

Form validations is one of the biggest worries of any frontend developer and no one likes to handle the boilerplate or utils when an elegant solution already exists.

In this article, we'll learn how to use [Formik](https://jaredpalmer.com/formik/) to build a robust form quickly.

We'll be using `create-react-app` project with following additional dependencies to setup quickly:
```sh
yarn add formik yup react-bootstrap bootstrap
```

There are 3 ways that formik can be used in a project:
1. `useFormik` react hook
2. `<Formik />` render props component
3. `withFormik()` higher order component

Formik recommends against using the `useFormik` react hook ([ref](https://jaredpalmer.com/formik/docs/api/useFormik#use-cases-for-useformik))

So, we're left with options 2 & 3.

In this post, we'll create a form using `<Formik />` render props component.

Link to full source code: https://codesandbox.io/s/github/dpkshrma/formik_react_starter

First, let us setup our form by directly using components from `react-bootstrap`:

```jsx
// SignupForm.js

import { Form, Button } from 'react-bootstrap';

const SignupForm = () => {
  return (
    <Form noValidate onSubmit={handleSubmit}>
      <Form.Group>
        <Form.Label>Name</Form.Label>
        <Form.Control
          type="text"
          name="name"
          placeholder="Please enter your name"
        />
      </Form.Group>
      <Form.Group>
        <Form.Label>Email</Form.Label>
        <Form.Control
          type="email"
          name="email"
          placeholder="Please enter your email address"
        />
      </Form.Group>
      <Form.Group>
        <Form.Label>Password</Form.Label>
        <Form.Control
          type="password"
          name="password"
          placeholder="Please enter a strong password"
        />
      </Form.Group>
    </Form>
  )  
}

export default SignupForm;
```

Now, let us wrap it inside `<Formik />` to access all the validation helper functions & state it provides:

```jsx
import { Formik } from 'formik';

const SignupForm = () => {
  const onSuccess = (values) => {
    alert('All entries are valid' + JSON.stringify(values));
  };
  return (
    <Formik
      onSubmit={onSuccess}
      initialValues={{
        name: '',
        password: '',
        email: ''
      }}
    >
      {({
        handleSubmit,
        handleChange,
        values,
        touched,
        errors,
      }) => {
        return (
          <Form noValidate onSubmit={handleSubmit}>
            <Form.Control
              type="text"
              name="name"
              placeholder="Please enter your name"
              value={values.name}
              onChange={handleChange}
              isInvalid={errors.name}
            />
            <Form.Control.Feedback type="invalid">
              {errors.name}
            </Form.Control.Feedback>
            {/* ... */}
          </Form>
        );
      }}
    </Formik>
  );
}
```

As you can see, `<Formik />` allows us to set initial state of the form using `initialValues` prop, and handle the submitted values after validation.

Following the [render props](https://reactjs.org/docs/render-props.html) technique, `<Formik />` accepts a function as its child and provides a whole range of helper functions & state variables in function arguments. Some of them are:

- `handleSubmit` allows you to automatically handle all the html & custom validations on form submit
- `handleChange` can be used with `onChange` prop of all types of inputs and automatically updates the values correctly after validation (validation on change can be made optional)
- `values` object contains the dynamically updated input values. - `errors` object contains validation errors
The key in each key-value pair of `values` and `errors` objects come from the `name` attribute of the input form component.

Now, this is all well and good. We've covered html based validations, but what about custom validation requirements?
`<Formik />` has got you covered for this! You can provide custom form validation rules in the `validationSchema` prop.

We'll use `yup` to create validation schema. You can use `joi` as well if you prefer. Below example illustrate how to use the same:

```jsx
const schema = yup.object({
  name: yup.string().required(),
  password: yup.string()
    .matches(/^(?=.*?[A-Za-z])(?=.*?[0-9]).{8,32}$/, invalidPwdMsg)
    .required(),
  email: yup.string().email('A valid email is required').required(),
});

const SignupForm = () => {
  return (
    <Formik
      validationSchema={schema}
      onSubmit={onSuccess}
    >
      {/* ... */}
    </Formik>
  );
}
```
`yup` syntax is very similar to `joi`. It integrates very well with `Formik`, and has in built functions to check for email, regex etc. as shown above.

That's all for now! :)
You just learned how to quickly get started and build awesome forms with Formik in React.

Hit the like button if you like this post & follow me if you'd like to read more short tutorials like this.