You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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处理,避免多状态冲突。

修正方案

  1. 首先用React Hook Form自带的watch方法监听年份选择值,无需单独维护本地selectedYear状态:
// 表单初始化时引入watch和setValue
const { control, watch, setValue } = useForm();
// 监听selectedBirthYear的实时值
const selectedBirthYear = watch('selectedBirthYear');
  1. 修正年份选择器的Controller配置,正确透传field属性:
<Controller
  control={control}
  name="selectedBirthYear"
  defaultValue={years[0]}
  render={({ field }) => (
    <SelectBirthYear
      {...field}
      years={years}
    />
  )}
/>
  1. 在父组件直接写联动逻辑,通过setValue主动更新月份的表单值:
useEffect(() => {
  if (Number(selectedBirthYear?.name) === startYear) {
    setValue('selectedBirthMonth', reducedMonths[reducedMonths.length - 1]);
  }
}, [selectedBirthYear, setValue, startYear, reducedMonths]);
  1. 修正月份选择器的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 13:24:05