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

