React Form using Formik, Material-UI and Yup.
Tags: react, javascript, webdev
Published: 2018-10-23 13:11:16

---
title: React Form using Formik, Material-UI and Yup.
published: true
description: Form Validation in React using Formik, Material-ui and Yup.
tags: React, Javascript, Webdev
---

## Introduction

Sometimes managing forms in react can be a drag, And if you decide to use libraries like redux-form they carry significant performance overhead which you might not be able to afford in the application you are building. Formik is here to your rescue, it is a small library with bundle size of 12 kB compared to redux-form which has a bundle size of 22.5 kB minified gzipped, and the best part; Formik helps with the wearisome task of form handling, which are

- Handling form state
- Handling form validation and errors
- Handling form submission

You can check the docs for more information about the library on [Formik](https://jaredpalmer.com/formik)

Formik also seamlessly integrates with material-ui; it is a react library that implement Google material design, providing components like input, button, label and several others out of the box.

You can also check out their docs for more information [Material-Ui](http://material-ui.com/)

Finally, there is Yup. What is Yup? It is a JavaScript object schema validator and object parser. In this context Yup simply helps handle validation. This does not mean that you can’t write your own custom validator for Formik but I find my experience using Yup good and it improves the readability of my code.

More on Yup here in the docs [Yup](https://www.npmjs.com/package/yup).

This article will explain how to build forms and handle form validation with Formik, Yup and Material-UI.

Here is a quick overview of what we are going to do in this guide:

- Create a react app using create-react-app.
- Create a simple form with Material-UI and Formik.
- Write validation rules/ validation schema with Yup.
- Use Yup with Formik.

This tutorial assumes you have knowledge of react.

There is a code sandbox demo of the form we are going to build here:
[Formik Demo Application](https://codesandbox.io/s/ol11mmk30z)

### Installation:

* Create react application using CRA [Create React App](https://github.com/facebook/create-react-app)
``` Create-react-app formik-form-demo ```

After running this our project structure should look like this:

![File structure](https://thepracticaldev.s3.amazonaws.com/i/fv238hoxcca3720tzhow.JPG)

Now open the `App.js` file in the `src` folder and then delete the contents of the parent `div` that has a className of App.

![App.js](https://lh4.googleusercontent.com/w8XxgNeL9WNB2ZrQ0MF_YPYB5FAAapixo1CeXdP3N-j_yHzio4J7Em5U2iBsk7UhsKFygnqZGOYLEPOfUjee11UCwuZZq8NtiIq_tRluLmy0x2tSyI-x1TMdipWKn6YfKg)

In your terminal run 
```javascript
Yarn add or npm install formik yup @material-ui/core

```
This command adds formik, Yup and material-UI to our dependencies. Now that our dependencies have been installed, create a new folder called `InputForm` in the `src` folder then create `index.js` and `form.js` files in the `InputForm` folder.

This is what your src folder should look like now:

![src now](https://thepracticaldev.s3.amazonaws.com/i/6ghktpphit5kkcc7vmvv.JPG)

The `form.js` file is going to contain the presentation while the `index.js` is going to contain most of the logic.
Currently your application should be displaying a blank page, so right now let's just get our form displaying.

In your `form.js` file add the following code

```javascript
import React from "react";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";

export const Form = (props) => {
  return (
   <form onSubmit={() => {}}>
     <TextField
       id="name"
       name="name"
       label="Name"
       fullWidth
      
     />
     <TextField
       id="email"
       name="email"
       label="Email"
       fullWidth
     />
     <TextField
       id="password"
       name="password"
       label="Password"
       fullWidth
       type="password"
     />
     <TextField
       id="confirmPassword"
       name="confirmPassword"
       label="Confirm Password"
       fullWidth
       type="password"
     />
     <Button
       type="submit"
       fullWidth
       variant="raised"
       color="primary"
     >
       Submit
     </Button>
   </form>
 );
};


```

What we have done here is create a simple form with four fields (Name, Email, Password and Confirm password) and a Button with material-UI.

In `index.js` file in the `InputForm` folder add the following code:

```javascript

import React, { Component } from "react";
import { Formik } from "formik";
import withStyles from "@material-ui/core/styles/withStyles";
import { Form } from "./form";
import Paper from "@material-ui/core/Paper";

const styles = theme => ({
 paper: {
   marginTop: theme.spacing.unit * 8,
   display: "flex",
   flexDirection: "column",
   alignItems: "center",
   padding: `${theme.spacing.unit * 5}px ${theme.spacing.unit * 5}px ${theme
     .spacing.unit * 5}px`
 },
 container: {
   maxWidth: "200px"
 }
});

class InputForm extends Component {
 constructor(props) {
   super(props);
   this.state = {};
 }

 render() {
   const classes = this.props;
   return (
     <React.Fragment>
          <div className={classes.container}>
         <Paper elevation={1} className={classes.paper}>
           <h1>Form</h1>
           <Formik
             render={props => <Form {...props} />}
           />
         </Paper>
       </div>
     </React.Fragment>
   );
 }
}

export default withStyles(styles)(InputForm);




```

Here we have created a class component called `InputForm`. At the top we imported the form component we just created. And then passed it as a `render prop` to the `Formik` component.

There are three ways to render things with Formik
- `<Formik component />`
- `<Formik render />`
- `<Formik children />`

We used the `render props` in the above. All three render methods will be passed some props which include:

- errors
- handleChange
- handle
- isValid
- touched
- setFieldTouched

There are a couple more props passed to your component, check the docs for all of them [Formik Docs](https://github.com/jaredpalmer/formik)

Next go to the `App.js` file in the `src` folder, import the `InputForm` component then add it as a child of the `div`. This our `App.js` now and the form should be rendered.

```javascript
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import InputForm from './InputForm'

class App extends Component {
 render() {
   return (
     <div className="App">
       <InputForm/>
     </div>
   );
 }
}

export default App;

```

![initial form](https://lh5.googleusercontent.com/jjBRs0HyIS4F-zT58_JGnyEFk95S2Sb7bBrqdR3gg8KS-44VfGz4KzYwqQX3MXpMAcZZRszgXVEb6KbZwzMeUiukWA5Gp2tkp-QOlc9dp2AXIr5L8ItPjr3v4BtY80eZJ_HnfFXk)

Now We have our form rendered, Let’s start with the form validation. This is where Yup is needed, Basically Yup provides functions that helps us write intuitive validation rules.
First we import Yup into the `Index.js` file in the `InputForm` folder then we use its APIs to write our validation rules.

Import statement
`import * as Yup from "yup"`

**Note: importing all the functions/APIs of a library into your codebase is not a good practice.**

Now add this following code to the `Index.js` file in the `InputForm` folder, This is our validation rules or Validation scheme.

```javascript

const validationSchema = Yup.object({
name: Yup.string("Enter a name")
.required("Name is required"),
email: Yup.string("Enter your email")
.email("Enter a valid email")
.required("Email is required"),
password: Yup.string("")
.min(8, "Password must contain at least 8 characters")
.required("Enter your password"),
confirmPassword: Yup.string("Enter your password")
.required("Confirm your password")
.oneOf([Yup.ref("password")], "Password does not match")


```
I don’t know about you but at first glance this looks very intuitive. Yup provides several APIs which makes Object validation easy. Some of them are listed below.

##### APIs

`Yup.object()` : Is used to define the keys of the object and the schema for those key. In this examples it is used to define the fields we are validating (name, email, password, confirmPassword) and also define validation rules for those fields.

`Yup.string()`: Defines a string schema. This specifies that field should be a string, it also accepts an optional argument which is used to set the error message. All four fields we defined are strings. Also, we can chain functions or methods so that it is possible have more than one validation rule for each field.

`Yup.required()`: This specifies that field is required and must not be empty. It also takes an optional argument to define the error message.

`Yup.email()`: Defines a email schema and also takes an optional argument.

`Yup.min()`:  Sets the minimum length for the value. It accept two arguments, the length and the error message.

`Yup.ref()`:  It creates a reference to another sibling field or sibling descendant field. It accepts a compulsory argument which is the field we are referencing.

`Yup.oneOf()`:  Whitelist a set of values. It accepts an array of the whitelisted value/values and an optional argument that sets the error message.

Check the Docs for a full list of the APIs.

Now that we have defined our validation schema/rules, how do we integrate it into our application? 

Remember I earlier said that Yup seamlessly  integrates with Formik, well Formik provides a special prop for Yup called `validationSchema` which will automatically transform Yup's validation errors into a pretty object. So we pass our validation rules to the `validationSchema` prop. Formik also allows you to set initial value for your fields using the `initialValues` prop. 

So the render function of our `InputForm` component should look like this when we add the `validationSchema` and `initialValues` prop to the Formik component.

```javascript

render() {
  const classes = this.props;
  const values = { name: "", email: "", confirmPassword: "", password: "" };
  return (
<React.Fragment>
    <div className={classes.container}>
        <Paper elevation={1} className={classes.paper}>
        <h1>Form</h1>
        <Formik
            render={props => <Form {...props} />}
            initialValues={values}
            validationSchema={validationSchema}
        />
        </Paper>
    </div>
</React.Fragment>
);
}

```

We have defined the validation rules and initial values, Now let's use the props passed to the Form component to handle validate the inputs.

In our Form component in the `InputForm` folder, we destructure the props and create a change function which handles our input changes

```javascript
const {
values: { name, email, password, confirmPassword },
errors,
touched,
handleSubmit,
handleChange,
isValid,
setFieldTouched
} = props;


const change = (name, e) => {
e.persist();
handleChange(e);
setFieldTouched(name, true, false);
};


```

There are a couple of props passed to the Form component by `Formik` but I won’t be using all of them in this demo.
Props used are:

- values : An object that contains the initial values of the form fields.

- errors : An object containing error messages of the field.

- touched : An object containing fields that have been touched/visited, fields              that have been touched are set to true otherwise they are set to false.

- handleChange : General Input handler, This will update the values[key] where key is the event-emitting input's name attribute. If the name attribute is not present, handleChange will look for an input's id attribute.
 
- isValid: Returns true if there are no errors i.e (no errors in the errors object).

- setFieldTouched: is a function used to set the touched state of a field. The first argument is the name of the field, the second argument is the value you want to set the touched state to which is true and the last argument is a boolean used to prevent validation.

Now let's make changes to Form component so that we can see the error messages when there’s an error.
Material-UI `TextField` component provides two props which can help us display our error message in an elegant way, these props are `helperText` and `error` for displaying the error.

The Form component should look like this when we add these props to our `TextField` component.

```javascript

export const Form = props => {
 const {
   values: { name, email, password, confirmPassword },
   errors,
   touched,
   handleChange,
   isValid,
   setFieldTouched
 } = props;

 const change = (name, e) => {
   e.persist();
   handleChange(e);
   setFieldTouched(name, true, false);
 };
 return (
   <form
     onSubmit={() => {
       alert("submitted");
     }}
   >
     <TextField
       id="name"
       name="name"
       helperText={touched.name ? errors.name : ""}
       error={touched.name && Boolean(errors.name)}
       label="Name"
       value={name}
       onChange={change.bind(null, "name")}
       fullWidth
     
     />
     <TextField
       id="email"
       name="email"
       helperText={touched.email ? errors.email : ""}
       error={touched.email && Boolean(errors.email)}
       label="Email"
       fullWidth
       value={email}
       onChange={change.bind(null, "email")}
     
     />
     <TextField
       id="password"
       name="password"
       helperText={touched.password ? errors.password : ""}
       error={touched.password && Boolean(errors.password)}
       label="Password"
       fullWidth
       type="password"
       value={password}
       onChange={change.bind(null, "password")}
      
     />
     <TextField
       id="confirmPassword"
       name="confirmPassword"
       helperText={touched.confirmPassword ? errors.confirmPassword : ""}
       error={touched.confirmPassword && Boolean(errors.confirmPassword)}
       label="Confirm Password"
       fullWidth
       type="password"
       value={confirmPassword}
       onChange={change.bind(null, "confirmPassword")}
      
     />
     <Button
       type="submit"
       fullWidth
       variant="raised"
       color="primary"
       disabled={!isValid}
     >
       Submit
     </Button>
   </form>
 );
};



```

You should notice that I added three props to the `Textfield` component, `helperText`, `error` and `onChange`.
`onChange` is set to the change function we wrote above for handling changes to the input field.
The `helperText` prop is set to a ternary operator (If statement) that states if the field is touched, set the `helperText` prop to the error message of that field else set it to an empty string. The `error` prop is set to a boolean to indicate an error in validation.

And finally the `Button` component has a prop called `disabled` which disables the button, we set it to not `!isValid` so if there is any error in the errors object the button remains disabled, I mean we don’t want to be submitting invalid values.

![working final form](https://lh3.googleusercontent.com/g4xGDrOUKZzvQMjH9UgQI0IXuTwMw17-a_T6O0Zuj77Gsj8EhWcTUOBv_SjHscppBcM5d21IuecBP7ESA4Gou8nyafNKAEn-2F3TbXJAxNBzwM5IyRiew2xYKn-GFMPs3oVW-dET)

Creating forms with Formik,Material-UI and Yup is awesome.
 
This is my first technical article/post so I am open to any suggestion that can help improve my writing.

If you have any question or suggestion comment below.

_Special thanks to my friend [YJTheRuler](https://twitter.com/YJTheRuler) for editing this article, He writes for [@radronline](https://t.co/kiG4o0nHFY) about Afro-beat music and African culture._