- 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.
Updating to onChange Mode
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.
Using all Mode for Comprehensive Validation
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
mode: 'all',
resolver: yupResolver(schema),
})
Benefits:
- Combines
onBlurandonChangevalidation 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
Why does validation fail in **onBlur** mode?
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.
