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

React Hook Form无法读取Headless UI自定义Select组件的提交值怎么办

问题根源
    1. register使用位置错误:React Hook Form的register方法仅支持原生表单DOM元素(input、select、textarea等),你将其绑定在Headless UI的Listbox.Options自定义组件上,无法自动触发值变更监听和状态同步。
    1. 自定义状态未同步到RHF:你当前在父组件维护了selectedYear、selectedMonth这类外部受控状态,但是没有将状态变更同步到React Hook Form的表单存储中,导致提交时RHF无法收集到对应字段的值。
解决方案

官方推荐使用Controller组件对接自定义受控组件,不需要使用register,修改步骤如下:

1. 修改SelectBirthYear组件

用Controller接管字段状态,直接绑定到React Hook Form:

import { useFormContext, Controller } from 'react-hook-form';
import { Listbox, Transition, Fragment } from '@headlessui/react';
// 其他导入(SelectorIcon、ListboxOption等)保持不变

export const SelectBirthYear = ({ years }) => {
  const { control } = useFormContext();
  return (
    <Controller
      // 对应表单字段名
      name="birthYear"
      control={control}
      // 可自定义默认值
      defaultValue={null}
      render={({ field }) => (
        <Listbox 
          value={field.value}
          onChange={field.onChange}
        >
          {({ open }) => (
            <>
              <Listbox.Label className="block text-sm font-medium text-gray-700 xs:text-xs">Geburtsjahr</Listbox.Label>
              <div className="mt-1 relative">
                <Listbox.Button className="bg-white relative w-full border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-yellow-500 focus:border-yellow-500 sm:text-sm">
                  <span className="block truncate">{field.value?.name || '请选择年份'}</span>
                  <span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
                    <SelectorIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
                  </span>
                </Listbox.Button>
                <Transition
                  show={open}
                  as={Fragment}
                  leave="transition ease-in duration-100"
                  leaveFrom="opacity=100"
                  leaveTo="opacity=0"
                >
                  <Listbox.Options
                    static
                    className="absolute z-10 mt-1 w-full bg-white shadow-lg max-h-60 rounded-md py-1 text-base ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm"
                  >
                    {years.map((year, index) => (
                      <ListboxOption
                        key={index}
                        value={year}
                        date={year.name}
                      />
                    ))}
                  </Listbox.Options>
                </Transition>
              </div>
            </>
          )}
        </Listbox>
      )}
    />
  )
}

2. 修改父组件调用逻辑

不需要再传value和onChange参数,状态已经交由React Hook Form管理:

<SelectBirthYear years={years} />

如果需要在父组件拿到选中的年份做月份联动,可以用watch方法监听字段值:

// 父组件内
const { watch } = useFormContext();
// 实时获取birthYear的选中值
const selectedYear = watch('birthYear');

3. 同理修改SelectBirthMonth组件

按照同样的逻辑修改SelectBirthMonth,将Controller的name属性设为birthMonth即可,提交时就能正常获取两个下拉选择的字段值。


内容的提问来源于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.30 18:36:01