Quick form validation set up in React using Formik and Yup.

1.Introduction.

We all know how tedious a process it is to validate forms using plain Javascript. So Formik and Yup are here to save the day.
In short, Formik offers us methods to handle form inputs that can be set up in no time. Yup helps us to define the validation schema which Formik uses to validate those inputs.

To begin with, we need these things along with React.

MUI v5 — Design form using built-in input components.
Formik — Wrapper to handle form components.
Yup — Define validation schema for form data.

2.Design a simple form using Material UI.

To start off with, we will design a simple form using Material to understand the fundamentals.

I have left the code for the above design below.

 

<div
className=“App”
style={{
width : ‘100vw’,
height : ‘100vh’,
overflowY : ‘auto’,
display : ‘flex’,
justifyContent : ‘center’,
alignItems : ‘start’,
background: ‘linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(172,45,157,1) 35%, rgba(0,212,255,1) 100%)’
}}
>
<form
style={{
margin : ‘0 auto’,
display : ‘flex’,
flexDirection : ‘column’,
minWidth : ‘30%’,
background : ‘white’,
padding : ’20px’,
borderRadius : ’20px’,
marginTop : ’20px’
}}>
<Typography
variant=’h5′
textAlign=’center’
marginBottom=’20px’
style={{color : ‘grey’}}
>SIGN UP</Typography>
<TextField
label = ‘Email’
style={{marginBottom : ’20px’}}
name = ’email’
/>
<TextField
label = ‘Password’
type=’password’
style={{marginBottom : ’20px’}}
name = ‘password’
/>
<TextField
label = ‘Full name’
style={{marginBottom : ’20px’}}
name = ‘fullName’
/>
<TextField
label = ‘Age’
type = ‘number’
name = ‘age’
style={{marginBottom : ’20px’}}
/>
<FormControl>
<RadioGroup
style={{display : ‘flex’, flexDirection : ‘row’}}
value={gender}
name = ‘gender’
onChange={handleChange}
>
<FormControlLabel
control={<Radio value=’male’/>}
label = ‘Male’
labelPlacement=’end’
/>
<FormControlLabel
control={<Radio value=’female’/>}
label = ‘Female’
labelPlacement=’end’
/>
<FormControlLabel
control={<Radio value=’other’/>}
label = ‘Other’
labelPlacement=’end’
/>
</RadioGroup>
</FormControl>
<FormControl >
<FormControlLabel
control={<Checkbox checked={agree}/>}
label = ‘Agree to terms and conditions.’
labelPlacement=’end’
name = ‘agree’ onChange={handleChange}
/>
</FormControl>
<Box display=’flex’ justifyContent=’space-between’>
<Button>Reset</Button>
<Button>Submit</Button>
</Box>
</form>
</div>

 

3.Create an initial state for the form inputs.

We need an initial state variable for the form inputs used. The use State declaration for the inputs looks like this.

const [initialState,setInitialState] = useState({email : ”,

password : ”,

fullName : ”,

age : ”,

gender : ”,

agree : false

})

 

4.Construct validation schema for the form inputs using Yup.

The validation schema can be declared outside the component since it is a one-time declaration.

The validation done for each input is self-explanatory. But, I have left a few comments for clarity.

// Create a new object with the shape of our input initial state variable.const VALIDATION_SCHEMA = yup.object().shape({

// Yup provides inbuilt method to validate email.

email : yup.string()

.email(‘Please enter a valid email.’)

.required(‘Email cannot be empty.’),

// We can also use regular expressions to validate passwords.

password : yup.string()

.matches(/^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{4,}$/,

‘Password must contain atleast 1 lowercase, 1 uppercase, 1 number and 1 special character.’)

.min(8,’Password must have atleast 8 Charaters.’)

.required(‘Password cannot be empty.’),

// Ensure name is minimum of 3 characters.

fullName : yup.string()

.min(3,’Name should atleast have 3 characters.’)

.max(30,’Name should not exceed 30 characters.’)

.required(‘Name cannot be empty.’),

// Making sure user’s age is above 18.

age : yup.number()

.min(18,’Should be atleast 18 years of age.’)

.required(‘Age cannot be empty.’),

// User must choose one of the three options for gender from the form.

gender : yup.string()

.required(‘Please select any one option.’),

// If the checkbox state is not true, then we show an error message.

agree : yup.bool().oneOf([true],’Please agree to the terms and conditions to proceed.’)

})

 

5.Handle the functionality of the form using Formik.

It’s time for Formik to take control and do the magic we have been waiting for.

First, we have to wrap the form tag using Formik component which will give us access to the methods and data necessary for the form.

 

<Formik// The initial state that we created above.

initialValues={{…initialState}}

// If the initial values are changed in the state, formik will consider them as the new state.

enableReinitialize = {true}

// The schema that we declared above

validationSchema={VALIDATION_SCHEMA}

// We will not validate on change, instead we will do it on blur.

validateOnChange = {false}

validateOnBlur = {true}

// The values object contains the latest state of input.

// This method will not be called if there is any error in any one of the input field.

onSubmit={(values) => setShowSuccess(true)}

>

{({

// values is an object that contains the input data

values,

// The error object contains details of input fields with error

// eg : {fieldName1 : errorMessage1, fieldNamw2 : errorMessag2}

errors,

// Formik will handle input change and blur. We just have to pass the methods to each input.

handleChange,

handleBlur,

// Submit and Reset handler has to be passed to their respective buttons.

handleSubmit,

handleReset

}) => {

const {email,password,fullName,age,gender,agree} = values

return (

<form

style={{

margin : ‘0 auto’,

display : ‘flex’,

flexDirection : ‘column’,

minWidth : ‘30%’,

background : ‘white’,

padding : ’20px’,

borderRadius : ’20px’,

marginTop : ’20px’

}}>

<Typography

variant=’h5′

textAlign=’center’

marginBottom=’20px’

style={{color : ‘grey’}}

>SIGN UP</Typography>

<TextField

label = ‘Email’

style={{marginBottom : ’20px’}}

name = ’email’

// Formik will control and handle the input component for us.

// This same technique will be repeated for all other inputs.

value = {email}

onChange={handleChange}

onBlur = {handleBlur}

// Checking if error object contains email field.

error = {!!errors.email}

// If there is error message, it will be displayed to the user.

helperText = {errors.email}

/>

<TextField

label = ‘Password’

type=’password’

style={{marginBottom : ’20px’}}

name = ‘password’

value = {password}

onChange={handleChange}

onBlur = {handleBlur}

error = {!!errors.password}

helperText = {errors.password}

/>

<TextField

label = ‘Full name’

style={{marginBottom : ’20px’}}

name = ‘fullName’

value = {fullName}

onChange={handleChange}

onBlur = {handleBlur}

error = {!!errors.fullName}

helperText = {errors.fullName}

/>

<TextField

label = ‘Age’

type = ‘number’

name = ‘age’

style={{marginBottom : ’20px’}}

value = {age}

onChange={handleChange}

onBlur = {handleBlur}

error = {!!errors.age}

helperText = {errors.age}

/>

<FormControl error={!!errors.gender}>

<RadioGroup

style={{display : ‘flex’, flexDirection : ‘row’}}

name = ‘gender’

value={gender}

onChange={handleChange}

>

<FormControlLabel

control={<Radio value=’male’/>}

label = ‘Male’

labelPlacement=’end’

/>

<FormControlLabel

control={<Radio value=’female’/>}

label = ‘Female’

labelPlacement=’end’

/>

<FormControlLabel

control={<Radio value=’other’/>}

label = ‘Other’

labelPlacement=’end’

/>

</RadioGroup>

{errors.gender ? <FormHelperText>{errors.gender}</FormHelperText> : null}

</FormControl>

<FormControl error={!!errors.agree}>

<FormControlLabel

control={<Checkbox checked={agree}/>}

label = ‘Agree to terms and conditions.’

labelPlacement=’end’

name = ‘agree’ onChange={handleChange}

/>

{errors.agree ? <FormHelperText>{errors.agree}</FormHelperText> : null}

</FormControl>

<Box display=’flex’ justifyContent=’space-between’>

<Button onClick={handleReset}>Reset</Button>

<Button onClick={handleSubmit}>Submit</Button>

</Box>

</form>

)

}}

</Formik>

 

6.Conclusion

That’s it. We are good to go.

You should see validation happening in the fields as expected, which look something like this.

You can refer to the documentation for deeper concepts in form handling which Formik offers.

Connect With Us!