I am creating a form with React-Hook-Form.
I have set useForm({mode: 'onBlur'})
to trigger validation instantly and show error message right after user onBlur an element.
For input text fields, it works fine.
However, it doesn't work with my <Controller />
element, which wraps an customized <Select />
.
The following is my code:
import React from 'react';
import { useForm, Controller, ErrorMessage } from 'react-hook-form';
import Select from '../../ponents/UI/Select';
const departmentList = [
{ name: 'PLEASE SELECT', value: '' },
{ name: 'Finance', value: 'FIN' },
{ name: 'IT', value: 'IT' },
{ name: 'Business', value: 'BIZ' }
];
const Form = props => {
const { register, handleSubmit, control, errors } = useForm({ mode: "onBlur" });
const onSubmit = (data) => {
console.log(data);
}
return (
<form onSubmit={handleSubmit(onSubmit)} style={{backgroundColor: 'white'}}>
<div>
<label>First Name:</label>
<input type="text" name='firstName' ref={register({ required: 'First name cannot be null.' })} />
<ErrorMessage errors={errors} name='firstName' />
</div>
<div>
<label>Last Name:</label>
<input type='text' name='lastName' ref={register({ required: 'Last name cannot be null.' })} />
<ErrorMessage errors={errors} name='lastName' />
</div>
<div>
<label>Department:</label>
<Controller
as={<Select options={departmentList} />}
control={control}
valueName="selected"
rules={{ required: 'Department cannot be null.' }}
name="department"
/>
<ErrorMessage errors={errors} name='department' />
</div>
<input type="submit" value="Submit" />
</form>
);
}
export default Form;
I am creating a form with React-Hook-Form.
I have set useForm({mode: 'onBlur'})
to trigger validation instantly and show error message right after user onBlur an element.
For input text fields, it works fine.
However, it doesn't work with my <Controller />
element, which wraps an customized <Select />
.
The following is my code:
import React from 'react';
import { useForm, Controller, ErrorMessage } from 'react-hook-form';
import Select from '../../ponents/UI/Select';
const departmentList = [
{ name: 'PLEASE SELECT', value: '' },
{ name: 'Finance', value: 'FIN' },
{ name: 'IT', value: 'IT' },
{ name: 'Business', value: 'BIZ' }
];
const Form = props => {
const { register, handleSubmit, control, errors } = useForm({ mode: "onBlur" });
const onSubmit = (data) => {
console.log(data);
}
return (
<form onSubmit={handleSubmit(onSubmit)} style={{backgroundColor: 'white'}}>
<div>
<label>First Name:</label>
<input type="text" name='firstName' ref={register({ required: 'First name cannot be null.' })} />
<ErrorMessage errors={errors} name='firstName' />
</div>
<div>
<label>Last Name:</label>
<input type='text' name='lastName' ref={register({ required: 'Last name cannot be null.' })} />
<ErrorMessage errors={errors} name='lastName' />
</div>
<div>
<label>Department:</label>
<Controller
as={<Select options={departmentList} />}
control={control}
valueName="selected"
rules={{ required: 'Department cannot be null.' }}
name="department"
/>
<ErrorMessage errors={errors} name='department' />
</div>
<input type="submit" value="Submit" />
</form>
);
}
export default Form;
The following is the <Select />
element:
import React from 'react';
const Select = props => {
let optionList = null;
if(props.options) {
optionList = props.options.map((o, i) => <option key={i} value={o.value}>{o.name}</option>)
}
return (
<select
className="form-control"
value={props.value}
style={props.style}
selected={props.selected}
onChange={props.onChange}
>
{ optionList }
</select>
);
};
export default Select;
After clicking on the select, choosing the empty value, and then blur, it doesn't show the error message onBlur.
Is there any way to make the trigger validation and show error message onBlur? Do I missed anything?
Share Improve this question asked May 7, 2020 at 15:19 theedchentheedchen 2,0544 gold badges11 silver badges21 bronze badges 1-
With the new version of react-hook-form, it works fine just using
useForm({ mode: "onBlur" })
– jordiburgos Commented Aug 29, 2022 at 15:06
1 Answer
Reset to default 2react-hook-form
cannot directly direct the blur
state of select ponent. Instead what it does is to send in the onBlur
function to the ponent passed to controller. You have to receive the prop and add it to your custom select.
const Select = props => {
let optionList = null;
if(props.options) {
optionList = props.options.map((o, i) => <option key={i} value={o.value}>{o.name}</option>)
}
return (
<select
className="form-control"
value={props.selected}
style={props.style}
onChange={props.onChange}
onBlur={props.onBlur}
>
{ optionList }
</select>
);
};
An HTML select by default receives it's value through the value
property, so the selected
does not do anything on the select. It is props.selected
because you have set valueName
as selected
on the controller.
Stackblitz