使用 Controller 时,react-hook-form 不会触发 onSubmit
react-hook-form not triggering onSubmit when using Controller
我有以下表格:
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="voucherPrice"
control={control}
defaultValue={false}
rules={{ required: true }}
render={({ field: { onChange, value, ref } }) => (
<Input {...field} onChange={(ev) => handlePriceInputChange(ev)} value={price} type="number" innerRef={ref} />
)}
/>
<p>{errors.voucherPrice?.message}</p>
<Button
variant="contained"
sx={{ mt: 1, mr: 1 }}
type="submit"
>
{"Continue"}
</Button>
</form>
并使用此配置:
function PriceSelection(props) {
const {
register,
handleSubmit,
control,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
});
const onSubmit = (data) => {
console.log("does not work?", data);
};
const classes = useStylesPriceSelection();
const [selected, setSelected] = useState(false);
const [price, setPrice] = useState("");
const handlePriceInputChange = (ev) => {
console.log("change", price);
setPrice(parseInt(ev.target.value));
};
当我按下提交按钮时函数onSubmit
没有触发。此外,我希望输入字段默认由状态 price
填充,当我按下提交按钮时,它的值将与函数 onSubmit
上的参数 data
一起发送。
您将 useState
与 react-hook-form
混合使用并且未更新 react-hook-form
的内部表单状态。您不需要为您的字段声明 useState
。
在您的示例中,您正在从 <Controller />
的 field
对象中析构 onChange
,但您从未将其用于 <Input />
组件。因此 react-hook-form
无法更新它的表单状态。当您将字段设置为必填时,onSubmit
回调将不会被触发,因为 react-hook-form
永远不会收到它的更新或值。
正确的方法是:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, onChange, value, ...field } }) => (
<Input {...field} onChange={onChange} value={value} type="number" innerRef={ref} />
)}
/>
或更短:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, ...field } }) => (
<Input {...field} type="number" innerRef={ref} />
)}
/>
更新
如果您需要访问 <Controller />
之外的值,您应该使用 react-hook-form
的 watch
方法。这将允许您订阅 voucherPrice
字段的最新值并在您的组件中使用它 -> Docs
如果您想以编程方式设置或更新值,您可以使用 react-hook-form
-> Docs
中的 setValue
方法
const { control, handleSubmit, watch, setValue } = useForm();
const voucherPrice = watch("voucherPrice");
const onButtonClick = () => {
setValue("voucherPrice", <newValue>);
}
如果您确实需要一个单独的 useState
作为您的值,并且想要将其额外更新到您的 react-hook-form
字段更新,您可以执行以下操作:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, onChange, value, ...field } }) => (
<Input
{...field}
onChange={(v) => {
onChange(v);
handlePriceInputChange(v);
}}
value={value}
type="number"
innerRef={ref}
/>
)}
/>
但我建议只使用 react-hook-form
解决方案,因为它具有管理表单状态所需的所有功能。
我有以下表格:
<form onSubmit={handleSubmit(onSubmit)}>
<Controller
name="voucherPrice"
control={control}
defaultValue={false}
rules={{ required: true }}
render={({ field: { onChange, value, ref } }) => (
<Input {...field} onChange={(ev) => handlePriceInputChange(ev)} value={price} type="number" innerRef={ref} />
)}
/>
<p>{errors.voucherPrice?.message}</p>
<Button
variant="contained"
sx={{ mt: 1, mr: 1 }}
type="submit"
>
{"Continue"}
</Button>
</form>
并使用此配置:
function PriceSelection(props) {
const {
register,
handleSubmit,
control,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
});
const onSubmit = (data) => {
console.log("does not work?", data);
};
const classes = useStylesPriceSelection();
const [selected, setSelected] = useState(false);
const [price, setPrice] = useState("");
const handlePriceInputChange = (ev) => {
console.log("change", price);
setPrice(parseInt(ev.target.value));
};
当我按下提交按钮时函数onSubmit
没有触发。此外,我希望输入字段默认由状态 price
填充,当我按下提交按钮时,它的值将与函数 onSubmit
上的参数 data
一起发送。
您将 useState
与 react-hook-form
混合使用并且未更新 react-hook-form
的内部表单状态。您不需要为您的字段声明 useState
。
在您的示例中,您正在从 <Controller />
的 field
对象中析构 onChange
,但您从未将其用于 <Input />
组件。因此 react-hook-form
无法更新它的表单状态。当您将字段设置为必填时,onSubmit
回调将不会被触发,因为 react-hook-form
永远不会收到它的更新或值。
正确的方法是:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, onChange, value, ...field } }) => (
<Input {...field} onChange={onChange} value={value} type="number" innerRef={ref} />
)}
/>
或更短:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, ...field } }) => (
<Input {...field} type="number" innerRef={ref} />
)}
/>
更新
如果您需要访问 <Controller />
之外的值,您应该使用 react-hook-form
的 watch
方法。这将允许您订阅 voucherPrice
字段的最新值并在您的组件中使用它 -> Docs
如果您想以编程方式设置或更新值,您可以使用 react-hook-form
-> Docs
setValue
方法
const { control, handleSubmit, watch, setValue } = useForm();
const voucherPrice = watch("voucherPrice");
const onButtonClick = () => {
setValue("voucherPrice", <newValue>);
}
如果您确实需要一个单独的 useState
作为您的值,并且想要将其额外更新到您的 react-hook-form
字段更新,您可以执行以下操作:
<Controller
name="voucherPrice"
control={control}
rules={{ required: true }}
render={({ field: { ref, onChange, value, ...field } }) => (
<Input
{...field}
onChange={(v) => {
onChange(v);
handlePriceInputChange(v);
}}
value={value}
type="number"
innerRef={ref}
/>
)}
/>
但我建议只使用 react-hook-form
解决方案,因为它具有管理表单状态所需的所有功能。