Simplifying React Form Validation with Formik & Yup

Table of contents

// Author: Sivanand G Kamath
// Dated : 04/06/2023
/* 
Formik and Yup: Reducing Effort and Enhancing Convenience in Form Management

Formik is a powerful React library designed to simplify form management, particularly for complex forms.
It handles form state, validation, and submission efficiently, reducing the need for repetitive code.
With Formik, developers can easily manage form input, track form values, errors, and submission status, 
ensuring a smoother form-building process.

Yup, a schema validation library, works seamlessly with Formik to handle form validation. 
It simplifies defining validation rules, ensuring input accuracy with minimal code. 
Together, Formik and Yup streamline form development, improve code maintainability, 
and offer a more organized approach to form validation, saving time and effort.

sample:-
https://codesandbox.io/p/sandbox/formik-and-yup-tutorial-8d5vvq
*/


import { Button, Card, CardContent, CardHeader, Checkbox, Container, FormControl, FormControlLabel, FormHelperText, FormLabel, Grid, MenuItem, Radio, RadioGroup, Select, TextField } from '@mui/material';
import { DateTimePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import React from 'react'

// Formik is designed to manage forms with complex validation with ease. Formik supports synchronous and asynchronous 
// form-level and field-level validation. Furthermore, it comes with baked-in support 
// for schema-based form-level validation through Yup


const FormikForm = () => {

    /*
    *********** Formik 😍️***********
        Formik consists of mainly 4 components: - initialValues, ValidationSchema, OnSubmit, and the return component which is written in the return part of the React page
        eg: 
        const formik = useFormik({
        1️⃣️    initialValues: { name: formData.name || '',  // in case we need to repopulate the value, here I used formData variable
            //...  
        },
        2️⃣️ validationSchema: {
            if(formik.values.name.length <2){
                alert("Please provide proper Name")
            }
            //...
        },
        3️⃣️ onSubmit:(values) => {
            console.log(values);
            // or write form submit logic here
        }
        })

        In return part, the below is the syntax
        4️⃣️ <TextField
                label="Name"
                name="text"
                fullWidth
                value={formik.values.name}  
                onChange={formik.handleChange}
                onBlur={formik.handleBlur}
                error={formik.touched.name && Boolean(formik.errors.name)} // error msg
                helperText={formik.touched.name && formik.errors.name}
            />

    ***************--------------------------*******************

    Yup simplifies by doing validations such as email, passwords etc.
        here I modularized the code so that it becomes easy to understand!!🙂️ 

    */
    const validationSchema = Yup.object().shape({
        text: Yup.string().required('Required'),
        select: Yup.string().required('Required'),
        checkbox: Yup.bool().oneOf([true], 'Required'),
        radio: Yup.string().required('Required'),
        //email: Yup.string().email('Invalid email format').required('Email Id is required') //this is how YUP simplifies the validation of email etc
    });

    const formik = useFormik({
        initialValues: {
            text: '',
            select: '',
            checkbox: false,
            radio: '',
            datetime: null,
            multiSelect: [] || '',
        },
        validationSchema: validationSchema,
        onSubmit: (values) => {
            console.log(values);
        },
    });


    return (
        <div>
            <Container>
                <Card>
                    <CardHeader title="FormikForm with Yup validation"></CardHeader>
                    <CardContent>
                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                            <form onSubmit={formik.handleSubmit}>
                                <Grid container spacing={2}>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <TextField
                                            label="Text Field"
                                            name="text"
                                            fullWidth
                                            value={formik.values.text}
                                            onChange={formik.handleChange}
                                            onBlur={formik.handleBlur}
                                            error={formik.touched.text && Boolean(formik.errors.text)}
                                            helperText={formik.touched.text && formik.errors.text}
                                        />
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <FormControl fullWidth>
                                            <FormLabel>Select Field</FormLabel>
                                            <Select
                                                name="select"
                                                fullWidth
                                                value={formik.values.select}
                                                onChange={formik.handleChange}
                                                onBlur={formik.handleBlur}
                                                error={formik.touched.select && Boolean(formik.errors.select)}
                                            >
                                                <MenuItem value="">None</MenuItem>
                                                <MenuItem value="option1">Option 1</MenuItem>
                                                <MenuItem value="option2">Option 2</MenuItem>
                                            </Select>
                                            {formik.touched.select && formik.errors.select && (
                                                <FormHelperText error>{formik.errors.select}</FormHelperText>
                                            )}
                                        </FormControl>
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <FormControl fullWidth  >
                                            <FormLabel>Multi Select</FormLabel>
                                            <Select
                                                name="multiSelect"
                                                multiple
                                                fullWidth
                                                value={formik.values.multiSelect}
                                                onChange={formik.handleChange}
                                                onBlur={formik.handleBlur}
                                                renderValue={(selected) => selected.join(', ')}
                                                error={formik.touched.multiSelect && Boolean(formik.errors.multiSelect)}
                                            >
                                                <MenuItem value="option1">Option 1</MenuItem>
                                                <MenuItem value="option2">Option 2</MenuItem>
                                                <MenuItem value="option3">Option 3</MenuItem>
                                            </Select>
                                            {formik.touched.multiSelect && formik.errors.multiSelect && (
                                                <FormHelperText error>{formik.errors.multiSelect}</FormHelperText>
                                            )}
                                        </FormControl>
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <FormControlLabel
                                            control={
                                                <Checkbox
                                                    name="checkbox"
                                                    fullWidth
                                                    checked={formik.values.checkbox}
                                                    onChange={formik.handleChange}
                                                    onBlur={formik.handleBlur}
                                                    error={formik.touched.checkbox && Boolean(formik.errors.checkbox)}
                                                />
                                            }
                                            label="Checkbox"
                                        />
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <FormControl component="fieldset">
                                            <FormLabel component="legend">Radio Buttons</FormLabel>
                                            <RadioGroup
                                                name="radio"
                                                fullWidth
                                                value={formik.values.radio}
                                                onChange={formik.handleChange}
                                                onBlur={formik.handleBlur}
                                                error={formik.touched.radio && Boolean(formik.errors.radio)}
                                            >
                                                <FormControlLabel value="option1" control={<Radio />} label="Option 1" />
                                                <FormControlLabel value="option2" control={<Radio />} label="Option 2" />
                                                <FormControlLabel value="option3" control={<Radio />} label="Option 3" />
                                            </RadioGroup>
                                            {formik.touched.radio && formik.errors.radio && (
                                                <FormHelperText error>{formik.errors.radio}</FormHelperText>
                                            )}
                                        </FormControl>
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <LocalizationProvider dateAdapter={AdapterDayjs}>
                                            <DateTimePicker
                                                label="Date and Time"
                                                name="datetime"
                                                fullWidth
                                                value={formik.values.datetime}
                                                onChange={(value) => formik.setFieldValue('datetime', value)}
                                                onBlur={formik.handleBlur}
                                                renderInput={(params) => <TextField {...params} />}
                                                error={formik.touched.datetime && Boolean(formik.errors.datetime)}
                                                helperText={formik.touched.datetime && formik.errors.datetime}
                                            />
                                        </LocalizationProvider>
                                    </Grid>
                                    <Grid item xs={12} md={12} lg={12} xl={12}>
                                        <Button type="submit" variant="contained" color="primary">Submit</Button>
                                    </Grid>
                                </Grid>
                            </form>
                        </LocalizationProvider>
                    </CardContent>
                </Card>
            </Container>
        </div>
    )
}

export default FormikForm
0
Subscribe to my newsletter

Read articles from Sivanand GKamath directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sivanand GKamath
Sivanand GKamath