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.
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.