- Published on
Fixing React Hook Form Validation in onBlur Mode
- Authors
- Name
- Ripal & Zalak
Fixing React Hook Form Validation in onBlur Mode
When working with React Hook Form and Yup for validation, you may encounter a scenario where validation behaves unexpectedly in onBlur
mode. This blog post will help you understand why this happens and how to fix it.
Problem Description
In a React application, consider the following code snippet using react-hook-form
with onBlur
validation mode and Yup schema:
import React, { useState } from 'react'
import { useForm } from 'react-hook-form'
import { yupResolver } from '@hookform/resolvers/yup'
import * as yup from 'yup'
import {
Checkbox,
Button,
FormControl,
FormLabel,
FormGroup,
FormControlLabel,
FormHelperText,
} from '@mui/material'
const schema = yup.object().shape({
option: yup.array().max(5, 'You can select up to 5 options only.'),
})
function App() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
mode: 'onBlur',
resolver: yupResolver(schema),
})
const onSubmit = (data) => {
alert(JSON.stringify(data))
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl component="fieldset" error={!!errors.option}>
<FormLabel component="legend">Select up to 5 options:</FormLabel>
<FormGroup>
{[...Array(8)].map((_, index) => (
<FormControlLabel
key={index}
control={
<Checkbox name="option" value={`Option${index + 1}`} {...register('option')} />
}
label={`Option ${index + 1}`}
/>
))}
</FormGroup>
<FormHelperText>
{errors.option?.message || 'You can select up to 5 categories.'}
</FormHelperText>
</FormControl>
<Button type="submit">Submit</Button>
</form>
)
}
export default App
Issue: Validation errors occur only after selecting the 7th checkbox instead of the 6th. This happens because onBlur
triggers validation when an input loses focus, but it evaluates the previous state of the form instead of the current state.
Solution
To resolve this, switch the mode
of useForm
to onChange
or all
.
onChange
Mode
Updating to const {
register,
handleSubmit,
formState: { errors },
} = useForm({
mode: 'onChange',
resolver: yupResolver(schema),
})
Benefits:
- Triggers validation whenever a checkbox is checked or unchecked.
- Ensures the form always evaluates the latest state.
all
Mode for Comprehensive Validation
Using const {
register,
handleSubmit,
formState: { errors },
} = useForm({
mode: 'all',
resolver: yupResolver(schema),
})
Benefits:
- Combines
onBlur
andonChange
validation modes. - Ideal for workflows that require both immediate feedback and focus-based validation.
Alternative: Manually Triggering Validation for Controlled Components
If you are using controlled components, ensure onBlur
is explicitly wired to the field’s validation function.
import { Controller, useFormContext } from 'react-hook-form'
const MyControlledField = ({ fieldName }) => {
const { control } = useFormContext()
return (
<Controller
name={fieldName}
control={control}
render={({ field: { onChange, onBlur, value } }) => (
<Checkbox checked={!!value} onChange={onChange} onBlur={onBlur} />
)}
/>
)
}
FAQs
onBlur
** mode?
Why does validation fail in **onBlur
mode triggers validation only when an input loses focus. If the validation depends on the state of multiple inputs, it may not capture changes accurately.
Which validation mode is best for performance?
Use onSubmit
for minimal re-renders, or onChange
if real-time validation is required.
Can I combine validation modes?
Yes, the all
mode combines onBlur
and onChange
for comprehensive validation.