React-Hook-Form Controller中useEffect失效 年月选择器联动无响应如何解决?
核心错误点
- 违反React Hook调用规则:
useEffect只能在组件顶层调用,你把它写在Controller的render回调的onChange属性中,属于嵌套函数内调用Hook,无法按预期执行,还会触发React官方规则警告。 - 没有正确透传
Controller提供的field属性:field对象自带绑定好的onChange、value等属性,你没有透传给自定义选择组件,反而额外维护了一套本地selectedYear/selectedMonth状态,导致React Hook Form托管的表单状态和本地状态完全不同步,selectedYear的实际值没有变化,自然不会触发监听它的useEffect。 - 联动逻辑位置不合理:把月份联动逻辑放在
SelectBirthMonth组件内部,不如直接在表单父层用React Hook Form自带的API处理,避免多状态冲突。
修正方案
- 首先用React Hook Form自带的
watch方法监听年份选择值,无需单独维护本地selectedYear状态:
// 表单初始化时引入watch和setValue const { control, watch, setValue } = useForm(); // 监听selectedBirthYear的实时值 const selectedBirthYear = watch('selectedBirthYear');
- 修正年份选择器的Controller配置,正确透传field属性:
<Controller control={control} name="selectedBirthYear" defaultValue={years[0]} render={({ field }) => ( <SelectBirthYear {...field} years={years} /> )} />
- 在父组件直接写联动逻辑,通过
setValue主动更新月份的表单值:
useEffect(() => { if (Number(selectedBirthYear?.name) === startYear) { setValue('selectedBirthMonth', reducedMonths[reducedMonths.length - 1]); } }, [selectedBirthYear, setValue, startYear, reducedMonths]);
- 修正月份选择器的Controller配置,根据年份动态传入可选月份列表:
<Controller control={control} name="selectedBirthMonth" defaultValue={months[0]} render={({ field }) => ( <SelectBirthMonth {...field} months={Number(selectedBirthYear?.name) === startYear ? reducedMonths : months} /> )} />
改完后年份变化时会自动触发watch返回值更新,进而触发联动useEffect执行,月份的表单值和可选列表都会同步更新,不需要在子组件内再单独维护状态。
内容的提问来源于stack exchange,提问作者Katharina Schreiber
相关产品推荐
相关产品推荐

