react-hook-form Controller 出错时如何聚焦?
How to focus when an error occurs in react-hook-form Controller?
我正在使用 react-hook-form 的 Controller
渲染自定义组件。
如果使用register
时出现错误,对焦正常,但Controller不正常
当自定义组件只处理一个输入时,我能够找到一种方法来处理错误,但是当它有多个输入时,我找不到一种方法来处理它。
Form.js
import { Controller, useForm } from "react-hook-form";
import CustomInput from "./CustomInput";
import * as yup from "yup";
const schema = yup.object({
name: yup.object().shape({
first: yup.string().required(),
last: yup.string().required(),
}),
});
function Form() {
const {
handleSubmit,
control,
formState: { errors },
} = useForm({
defaultValues: { name: { first: "", last: "" } },
resolver: yupResolver(schema),
});
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
rules={{ required: true }}
render={({ field }) => (
<CustomInput
value={field.value}
onChange={(value) => field.onChange(value)}
errors={errors}
/>
)}
/>
<button type="submit">Send</button>
</form>
);
}
export default Form;
CustomInput.js
function CustomInput({ value, onChange, errors }) {
const changeFirst = (e) => {
onChange({ first: e.target.value, last: value?.last });
};
const changeLast = (e) => {
onChange({ first: value?.first, last: e.target.value });
};
return (
<div>
<input type="text" value={value.first} onChange={changeFirst} />
<input type="text" value={value.last} onChange={changeLast} />
{errors?.name && (
<p className="errmsg">
{errors?.name?.first?.message || errors?.name?.last?.message}
</p>
)}
</div>
);
}
export default CustomInput;
自定义组件中有多个输入时,如何获取错误焦点?
您可以使用 RHF 中的 setFocus
。首先,检测 errors
对象何时更改,然后找到第一个包含该对象的字段并调用 setFocus(field)
:
const {
setFocus,
formState: { errors },
...
} = useForm<FormValues>();
React.useEffect(() => {
const firstError = Object.keys(errors).reduce((field, a) => {
return !!errors[field] ? field : a;
}, null);
if (firstError) {
setFocus(firstError);
}
}, [errors, setFocus]);
根据@NearHuscarl 的回答,我创建了 typescript 版本:
React.useEffect(() => {
const firstError = (
Object.keys(errors) as Array<keyof typeof errors>
).reduce<keyof typeof errors | null>((field, a) => {
const fieldKey = field as keyof typeof errors;
return !!errors[fieldKey] ? fieldKey : a;
}, null);
if (firstError) {
setFocus(firstError);
}
}, [errors, setFocus]);
我正在使用 react-hook-form 的 Controller
渲染自定义组件。
如果使用register
时出现错误,对焦正常,但Controller不正常
当自定义组件只处理一个输入时,我能够找到一种方法来处理错误,但是当它有多个输入时,我找不到一种方法来处理它。
Form.js
import { Controller, useForm } from "react-hook-form";
import CustomInput from "./CustomInput";
import * as yup from "yup";
const schema = yup.object({
name: yup.object().shape({
first: yup.string().required(),
last: yup.string().required(),
}),
});
function Form() {
const {
handleSubmit,
control,
formState: { errors },
} = useForm({
defaultValues: { name: { first: "", last: "" } },
resolver: yupResolver(schema),
});
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="name"
control={control}
rules={{ required: true }}
render={({ field }) => (
<CustomInput
value={field.value}
onChange={(value) => field.onChange(value)}
errors={errors}
/>
)}
/>
<button type="submit">Send</button>
</form>
);
}
export default Form;
CustomInput.js
function CustomInput({ value, onChange, errors }) {
const changeFirst = (e) => {
onChange({ first: e.target.value, last: value?.last });
};
const changeLast = (e) => {
onChange({ first: value?.first, last: e.target.value });
};
return (
<div>
<input type="text" value={value.first} onChange={changeFirst} />
<input type="text" value={value.last} onChange={changeLast} />
{errors?.name && (
<p className="errmsg">
{errors?.name?.first?.message || errors?.name?.last?.message}
</p>
)}
</div>
);
}
export default CustomInput;
自定义组件中有多个输入时,如何获取错误焦点?
您可以使用 RHF 中的 setFocus
。首先,检测 errors
对象何时更改,然后找到第一个包含该对象的字段并调用 setFocus(field)
:
const {
setFocus,
formState: { errors },
...
} = useForm<FormValues>();
React.useEffect(() => {
const firstError = Object.keys(errors).reduce((field, a) => {
return !!errors[field] ? field : a;
}, null);
if (firstError) {
setFocus(firstError);
}
}, [errors, setFocus]);
根据@NearHuscarl 的回答,我创建了 typescript 版本:
React.useEffect(() => {
const firstError = (
Object.keys(errors) as Array<keyof typeof errors>
).reduce<keyof typeof errors | null>((field, a) => {
const fieldKey = field as keyof typeof errors;
return !!errors[fieldKey] ? fieldKey : a;
}, null);
if (firstError) {
setFocus(firstError);
}
}, [errors, setFocus]);