React Hook Form结合Zod使用自定义评分组件时验证失效问题
解决React Hook Form结合Zod验证自定义星级组件的问题
你遇到的核心问题是:手动修改隐藏input的value不会触发React Hook Form(RHF)的状态更新——RHF依赖表单元素的change事件跟踪值变化,直接操作DOM属性无法让RHF感知到值的更新,因此Zod验证时始终拿到空字符串。
以下是两种可行的解决方案,优先推荐第一种标准实现方式:
方案1:使用React Hook Form的Controller组件(推荐)
Controller是RHF官方提供的、专门用于整合非原生表单组件的工具,无需手动维护隐藏input,直接将自定义组件与RHF的表单状态绑定。
修改父组件代码
import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import { zodResolver } from "@hookform/resolvers/zod"; import StarRatingInput from "./StarRatingInput"; // Zod验证规则 const FormSchema = z.object({ rating: z.string().refine( (value) => { const validRatings = ["1", "2", "3", "4", "5"]; return validRatings.includes(value); }, { message: "请选择有效的星级" }, ), }); type FormValues = z.infer<typeof FormSchema>; export default function RatingForm() { const { control, handleSubmit, formState: { errors } } = useForm<FormValues>({ resolver: zodResolver(FormSchema), defaultValues: { rating: "" } }); const onSubmit = (data: FormValues) => { console.log("提交数据:", data); }; return ( <form onSubmit={handleSubmit(onSubmit)}> <Controller name="rating" control={control} render={({ field: { onChange, value } }) => ( <StarRatingInput rating={value} setRating={onChange} // 直接将RHF的状态更新方法传给组件 /> )} /> {errors.rating && <p style={{ color: "red" }}>{errors.rating.message}</p>} <button type="submit">提交</button> </form> ); }
StarRatingInput组件无需修改
保持你原有的组件实现即可,它只需要负责渲染星级和触发值变更回调。
方案2:手动触发隐藏input的change事件(仅作参考)
如果不想使用Controller,需要在修改隐藏input的value后,手动触发change事件,让RHF感知到值的变化:
<StarRatingInput rating={rating} setRating={(newValue: string) => { setRating(newValue); const ratingInput = document.getElementById("rating") as HTMLInputElement; ratingInput.value = newValue; // 手动触发change事件,通知RHF更新状态 ratingInput.dispatchEvent(new Event("change")); }} /> <input hidden id="rating" type="text" {...register("rating")}/>
这种方式需要手动操作DOM,容易引发状态不同步问题,仅适合临时兼容场景。
内容的提问来源于stack exchange,提问作者raspace
相关产品推荐
相关产品推荐

