如何将react-hook-form的register与Headless UI Combobox配合使用
解决Headless UI Combobox与react-hook-form(register方式)集成的报错问题
问题分析
你遇到的Cannot read properties of undefined (reading 'name')错误主要来自两个原因:
- 直接将
react-hook-form的register方法挂载到Headless UI的Combobox组件上无效——Combobox并非原生表单控件,register无法处理其值变化逻辑。 - 当输入的查询文本无匹配选项时,
Combobox的value可能变为undefined,此时displayValue尝试访问person.name会触发空值报错。
解决方案代码
import React, { useState } from "react"; import { Combobox } from "@headlessui/react"; import { useForm } from "react-hook-form"; const people = [ { id: 1, name: "Durward Reynolds" }, { id: 2, name: "Kenton Towne" }, { id: 3, name: "Therese Wunsch" }, { id: 4, name: "Benedict Kessler" }, { id: 5, name: "Katelyn Rohan" }, ]; function Example() { const [query, setQuery] = useState(""); const { register, handleSubmit, setValue, watch, formState: { errors } } = useForm({ defaultValues: { assignee: people[0] } }); const selectedPerson = watch("assignee"); const filteredPeople = query === "" ? people : people.filter(person => person.name.toLowerCase().includes(query.toLowerCase()) ); const submit = (data) => { console.log(JSON.stringify(data)); }; return ( <form onSubmit={handleSubmit(submit)}> <Combobox as="div" value={selectedPerson} onChange={(person) => { setValue("assignee", person); setQuery(person?.name || ""); }} > <Combobox.Input onChange={(event) => { const inputValue = event.target.value; setQuery(inputValue); const matchedPerson = people.find(person => person.name.toLowerCase() === inputValue.toLowerCase() ); setValue("assignee", matchedPerson || undefined); }} displayValue={(person) => person?.name || ""} /> <Combobox.Options> {filteredPeople.map((person) => ( <Combobox.Option key={person.id} value={person}> {person.name} </Combobox.Option> ))} </Combobox.Options> </Combobox> {errors.assignee && <p style={{ color: "red" }}>请选择一个联系人</p>} <button type="submit">提交</button> </form> ); } export default function Check() { return ( <div> <Example /> </div> ); }
关键改动说明
- 表单默认值配置:将原
Combobox的defaultValue移至useForm的defaultValues中,确保表单初始状态与组件同步。 - 状态同步:用
watch("assignee")获取表单当前选中值,作为Combobox的value,双向绑定组件与表单状态。 - 手动更新表单值:移除
Combobox上的register,改为在Combobox的onChange事件中调用setValue更新表单值,同时同步输入框的查询文本。 - 输入逻辑处理:在
Combobox.Input的onChange中,检查输入文本是否匹配选项,匹配则自动选中对应项,否则将表单值设为undefined。 - 空值防护:修改
displayValue为person?.name || "",用可选链操作符避免空值访问报错。
内容的提问来源于stack exchange,提问作者Nilan Saha
相关产品推荐
相关产品推荐

