react-hook-form:使用 onBlur 模式时验证不起作用
react-hook-form: Validation not working when using onBlur mode
当用户选择超过 5 个复选框但没有成功时,我试图用 yup
和 react-hook-form
显示错误。
而是在选中第七个复选框时显示错误。
这里是简化的代码:
imports...
const schema = yup.object().shape({
option: yup.array().max(5)
});
function App() {
const { register, handleSubmit, errors } = useForm({
mode: "onBlur",
resolver: yupResolver(schema)
});
const [state, setState] = useState({
wasSubmitted: false
});
const submit = async (data) => {
window.alert(JSON.stringify(data));
};
if (state.wasSubmitted) {
return <p>Congrats</p>;
} else {
return (
<>
<CssBaseline />
<Container maxWidth="sm">
<Typography variant="h2" component="h1">
My form
</Typography>
<form noValidate autoComplete="off" onSubmit={handleSubmit(submit)}>
<FormControl
component="fieldset"
error={!!errors.option}
>
<FormLabel component="legend">
Please select the category or categories of books the child is
interested in:
</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option1"
label="Option 1"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option2"
label="Option 2"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
label="Option3"
value="Option 3"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option4"
label="Option 4"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option5"
label="Option 5"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option6"
label="Option 6"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option7"
label="Option 7"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option8"
label="Option 8"
/>
<FormControlLabel
<FormHelperText>Up to five categories</FormHelperText>
</FormControl>
<Button
type="submit"
disableElevation
>
Submit
</Button>
</form>
</Container>
</>
);
}
}
export default App;
您还可以在这里找到项目的沙箱:
有什么想法吗?
正如@aadlc 所说,解决方案是将模式设置为onChange
或all
。我会解释原因。
来自 react-hook-form API docs:
mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit'
Name
Type
Description
onSubmit (Default)
string
Validation will trigger on the submit
event and invalid inputs will attach onChange
event listeners to re-validate them.
onBlur
string
Validation will trigger on the blur
event.
onChange
string
Validation will trigger on the change
event with each input, and lead to multiple re-renders. Warning: this often comes with a significant impact on performance.
onTouched
string
Validation will trigger on the first blur
event. After that, it will trigger on every change
event.
all
string
Validation will trigger on the blur
and change
events.
在您的代码中,表单模式是onBlur
。这意味着验证是在 blur
事件上触发的(取消对输入的关注)。当您 select 选项 n+1
时,它会触发来自选项 n
的模糊事件。
例如就在 select 第 6 个选项(无效)之前,blur
事件从第 5 个选项(有效)触发,因为您不再关注它,并从选项 1-5 验证,所以您有检查第 7 个选项以重新验证从 1 到 6 的选项。
-- select up to 5 options --
select option 4
blur event fires from option 4 -> validate -> pass
select option 5
blur event fires from option 5 -> validate -> pass
select option 6
blur event fires from option 6 -> validate -> fail
select option 7
将验证模式更改为 onChange
将验证 在 change
事件触发后,当所有值都是最新的时:
-- select up to 5 options --
select option 4
blur event fires from option 4
select option 5
change event fires from option 5 -> validate -> pass
blur event fires from option 5
select option 6
change event fires from option 6 -> validate -> fail
blur event fires from option 6
select option 7
change event fires from option 7 -> validate -> fail
将验证模式更改为 all
将在 blur
和 change
事件中进行验证,这在该工作流程中可能有点过分,但它也有效。
当用户选择超过 5 个复选框但没有成功时,我试图用 yup
和 react-hook-form
显示错误。
而是在选中第七个复选框时显示错误。
这里是简化的代码:
imports...
const schema = yup.object().shape({
option: yup.array().max(5)
});
function App() {
const { register, handleSubmit, errors } = useForm({
mode: "onBlur",
resolver: yupResolver(schema)
});
const [state, setState] = useState({
wasSubmitted: false
});
const submit = async (data) => {
window.alert(JSON.stringify(data));
};
if (state.wasSubmitted) {
return <p>Congrats</p>;
} else {
return (
<>
<CssBaseline />
<Container maxWidth="sm">
<Typography variant="h2" component="h1">
My form
</Typography>
<form noValidate autoComplete="off" onSubmit={handleSubmit(submit)}>
<FormControl
component="fieldset"
error={!!errors.option}
>
<FormLabel component="legend">
Please select the category or categories of books the child is
interested in:
</FormLabel>
<FormGroup>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option1"
label="Option 1"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option2"
label="Option 2"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
label="Option3"
value="Option 3"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option4"
label="Option 4"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option5"
label="Option 5"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option6"
label="Option 6"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option7"
label="Option 7"
/>
<FormControlLabel
control={<Checkbox name="option" inputRef={register} />}
value="Option8"
label="Option 8"
/>
<FormControlLabel
<FormHelperText>Up to five categories</FormHelperText>
</FormControl>
<Button
type="submit"
disableElevation
>
Submit
</Button>
</form>
</Container>
</>
);
}
}
export default App;
您还可以在这里找到项目的沙箱:
有什么想法吗?
正如@aadlc 所说,解决方案是将模式设置为onChange
或all
。我会解释原因。
来自 react-hook-form API docs:
mode: onChange | onBlur | onSubmit | onTouched | all = 'onSubmit'
Name | Type | Description |
---|---|---|
onSubmit (Default) | string | Validation will trigger on the submit event and invalid inputs will attach onChange event listeners to re-validate them. |
onBlur | string | Validation will trigger on the blur event. |
onChange | string | Validation will trigger on the change event with each input, and lead to multiple re-renders. Warning: this often comes with a significant impact on performance. |
onTouched | string | Validation will trigger on the first blur event. After that, it will trigger on every change event. |
all | string | Validation will trigger on the blur and change events. |
在您的代码中,表单模式是onBlur
。这意味着验证是在 blur
事件上触发的(取消对输入的关注)。当您 select 选项 n+1
时,它会触发来自选项 n
的模糊事件。
例如就在 select 第 6 个选项(无效)之前,blur
事件从第 5 个选项(有效)触发,因为您不再关注它,并从选项 1-5 验证,所以您有检查第 7 个选项以重新验证从 1 到 6 的选项。
-- select up to 5 options --
select option 4
blur event fires from option 4 -> validate -> pass
select option 5
blur event fires from option 5 -> validate -> pass
select option 6
blur event fires from option 6 -> validate -> fail
select option 7
将验证模式更改为 onChange
将验证 在 change
事件触发后,当所有值都是最新的时:
-- select up to 5 options --
select option 4
blur event fires from option 4
select option 5
change event fires from option 5 -> validate -> pass
blur event fires from option 5
select option 6
change event fires from option 6 -> validate -> fail
blur event fires from option 6
select option 7
change event fires from option 7 -> validate -> fail
将验证模式更改为 all
将在 blur
和 change
事件中进行验证,这在该工作流程中可能有点过分,但它也有效。