React Select初始渲染无法显示props传入的默认分类ID问题求助
问题
开发了一个可复用的下拉选择组件RHFSelect,用于项目新增与编辑场景:
- 新增项目时可正常设置分类;
- 编辑项目时,虽已将项目所属分类的
_id通过categoryIDprops传入组件,但下拉框初始渲染时无法显示选中的分类,后续渲染才会正常显示。
组件代码
export default function RHFSelect({ label, name, register, options, required, validationschema, errors, categoryID = "", }) { return ( <div> <select className="textField__input" {...register(name, validationschema)} id={name} defaultValue={categoryID} > <option value="">Please select the project category</option> {options.map((option) => { return ( <option key={option.value} value={option.value}> {option.label} </option> ); })} </select> {errors && errors[name] && ( <span className="text-error block text-sm mt-2"> {errors[name]?.message} </span> )} </div> ); }
补充说明
options为从数据库获取的分类列表;categoryID默认值为空字符串,编辑模式下传入对应分类ID;- 期望新增模式显示“Please select the project category”,编辑模式默认显示之前选中的分类。
解决方案
问题核心:React Hook Form的register方法会接管表单控件的值管理,直接设置defaultValue在异步场景(比如options从数据库加载)下会失效——初始渲染时options可能未获取完成,或者register的状态初始化逻辑覆盖了defaultValue。
方式一:使用React Hook Form的defaultValues配置(推荐)
在表单初始化时通过useForm的defaultValues设置对应字段默认值,而非在组件内用defaultValue:
// 父组件中初始化useForm const { register, errors } = useForm({ defaultValues: { // 编辑模式传入categoryID,新增模式为空 category: categoryID || "" } }); // 修改后的RHFSelect组件 export default function RHFSelect({ label, name, register, options, required, validationschema, errors, }) { return ( <div> <select className="textField__input" {...register(name, validationschema)} id={name} > <option value="">Please select the project category</option> {options.map((option) => ( <option key={option.value} value={option.value}> {option.label} </option> ))} </select> {errors && errors[name] && ( <span className="text-error block text-sm mt-2"> {errors[name]?.message} </span> )} </div> ); }
方式二:使用useController替代register(适合组件内控制默认值场景)
如果需要在组件内部处理默认值,用useController接管控件,确保初始值同步:
import { useController } from "react-hook-form"; export default function RHFSelect({ label, name, control, options, required, validationschema, errors, categoryID = "", }) { const { field } = useController({ control, name, rules: validationschema, defaultValue: categoryID, }); return ( <div> <select className="textField__input" {...field} id={name} > <option value="">Please select the project category</option> {options.map((option) => ( <option key={option.value} value={option.value}> {option.label} </option> ))} </select> {errors && errors[name] && ( <span className="text-error block text-sm mt-2"> {errors[name]?.message} </span> )} </div> ); } // 父组件传入control const { control, errors } = useForm(); <RHFSelect control={control} name="category" categoryID={categoryID} options={options} />
关键注意点
- React Hook Form的
register会优先使用useForm初始化时的defaultValues,而非控件自身的defaultValue,异步加载数据场景下,要确保defaultValues在数据就绪后初始化表单,或用reset方法更新默认值。 - 如果
options是异步获取的,需确保options加载完成后再渲染组件,或添加加载状态,避免初始渲染时无对应选项导致选中值无法显示。
内容的提问来源于stack exchange,提问作者Yahya
相关产品推荐
相关产品推荐

