Working With React, Formik and Yup

Form validation on the frontend is a painful task. Thanks to Formik, It will not just create a quick form but also has builtin functionality for onChange, onBlur etc. events. The Formik is designed to handle complex validation with ease. So, let’s just start building a simple SignUp form with React, Formik and Yup.

Signup Form

I have used Material UI that helps to create awesome user interfaces. Without any further delay, let’s install the dependencies.

Dependencies

  • React, React-DOM
  • Formik
  • Yup
  • MaterialUI

I am using the CRA ( Create-React-App ) tool, that helps to set up react app quickly.

npx create-react-app signup

Once the react setup complete, move to the working directory i.e. signup and installed the other dependencies.

npm install @material-ui/core formik yup

Next step is to create a separate file that holds our signup form. You are independent to create it wherever you want. I am going to create the Signup.js file at containers/auth directory.

Let’s first create the Signup Form UI with MaterialUI package.

import React from 'react';
import Button from '@material-ui/core/Button';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import Grid from '@material-ui/core/Grid';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import Container from '@material-ui/core/Container';

Next step is to add some custom styles by using the makeStyles hook.

const useStyles = makeStyles(theme => ({
    '@global': {
        body: {
            backgroundColor: theme.palette.common.white,
        },
    },
    paper: {
        marginTop: theme.spacing(8),
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
    },
    avatar: {
        margin: theme.spacing(1),
        backgroundColor: theme.palette.secondary.main,
    },
    form: {
        width: '100%',
        marginTop: theme.spacing(3),
    },
    submit: {
        margin: theme.spacing(3, 0, 2),
    },
}));

Next step is creating the stateless component because everything is handled by Formik package.

export default const Signup = () => {

    const classes = useStyles();

    return (
        <Container component="main" maxWidth="xs">
            <CssBaseline />
            <div className={classes.paper}>
                <Typography component="h1" variant="h5">
                    Sign up
                </Typography>
                <form className={classes.form}>
                    <Grid container spacing={2}>
                        <Grid item xs={12} sm={6}>
                            <TextField
                                autoComplete="fname"
                                name="firstName"
                                variant="outlined"
                                fullWidth
                                id="firstName"
                                label="First Name"
                                autoFocus
                            />
                        </Grid>
                        <Grid item xs={12} sm={6}>
                            <TextField
                                variant="outlined"
                                fullWidth
                                id="lastName"
                                label="Last Name"
                                name="lastName"
                                autoComplete="lname"
                            />
                        </Grid>
                        <Grid item xs={12}>
                            <TextField
                                variant="outlined"
                                fullWidth
                                id="email"
                                label="Email Address"
                                name="email"
                                autoComplete="email"
                            />
                        </Grid>
                        <Grid item xs={12}>
                            <TextField
                                variant="outlined"
                                fullWidth
                                name="password"
                                label="Password"
                                type="password"
                                id="password"
                                autoComplete="current-password"
                            />
                        </Grid>
                    </Grid>
                    <Button
                        type="submit"
                        fullWidth
                        variant="contained"
                        color="primary"
                        className={classes.submit}
                    >
                        Sign Up
                    </Button>
                </form>
            </div>
        </Container>
    );
};

Now our Signup form UI part is done. Next step is to use the Formik and Yup package. First import both packages.

....

import { Formik, Form } from 'formik';
import * as yup from 'yup';

....

Next is to implement the Yup. The Yup is a javascript object schema validator and object parser. Let’s create our SignupSchema that holds the validation rules.

let SignupSchema = yup.object().shape({
    firstName: yup.string().required('This field is required.'), 
    lastName: yup.string().required('This field is required.'), 
    email: yup.string().email().required('This field is required.'), 
    password: yup.string()
        .min(6, 'Password is too short.')
        .max(20, 'Password is too long.')
        .required('This field is required.')
});

Next step is to implement the Formik and add the Signup Schema to the validation schema property.

<Formik
    initialValues={{
        firstName: '', 
        lastName: '', 
        email: '', 
        password: ''
    }}
    validationSchema={SignupSchema}
    onSubmit={values => {
        console.log(values);
    }}
>
{({errors, handleChange, touched}) => (
    <Form className={classes.form}>
        .....
        .....
    </Form>
)}
</Formik>

We have 4 fields in our signup form i.e. First Name, Last Name, Email and Password respectively. We need to define the default value of all these 4 fields and we have initialValues property to set the default value. After that, we attached the validationSchema with SignupSchema like validationSchema={SignupSchema}. Later we added the function with onSubmit property.

The Formik component returns the many properties to attach with the form. We are using errors, handleChange and touched in our example. You can find more details about the properties at the documentation.

Next step is to display errors messages. As we already know that we have used the MaterialUI package for the design. So we have to use the error and helperText property in the TextField UI component.

<TextField
    error={errors.firstName && touched.firstName}
    autoComplete="fname"
    name="firstName"
    variant="outlined"
    fullWidth
    onChange={handleChange}
    id="firstName"
    label="First Name"
    autoFocus
    helperText={errors.firstName && touched.firstName ? errors.firstName : null}
/>