react-hooks-form结合NextUi Select时defaultValue失效问题
解决react-hooks-form + NextUI Select默认值不生效问题
核心问题分析
- 异步默认值加载时机:你用异步函数作为
defaultValues,组件初始挂载时表单还未拿到异步返回的数据,导致Select初始为空;且getValues在初始阶段也拿不到值,因为异步数据尚未加载完成。 - 类型不匹配:
fetchData返回的gender是数字类型(0/1),但SelectItem的key是字符串类型('0'/'1'),类型不匹配导致即使后续拿到值也无法选中对应选项。 - 自定义组件集成方式:NextUI的Select属于自定义表单组件,直接用
register绑定无法正确同步表单状态,需要借助react-hooks-form的Controller组件适配。
具体解决方案
1. 用Controller替代register集成Select
将Select用Controller包裹,手动管控value和onChange逻辑,确保状态同步:
case 'gender': return ( <div className='INPUT'> <Controller name={column.uid} control={control} rules={{ required: true }} render={({ field }) => ( <Select classNames={{ base: ['items-center'], label: ['w-[100px]'], mainWrapper: ['flex-1'], }} isRequired={true} label={column.name} key={column.uid} labelPlacement='outside-left' value={field.value?.toString()} // 将数字转为字符串,匹配SelectItem的key onChange={(e) => field.onChange(e.target.value)} > <SelectItem key='0' value='0'>man</SelectItem> <SelectItem key='1' value='1'>male</SelectItem> </Select> )} /> </div> )
注意给SelectItem添加
value属性,与key保持一致,确保选中时能正确传递值。
2. 处理异步默认值的加载状态
利用formState.isLoading判断异步默认值是否加载完成,避免初始渲染空状态:
const { ..., formState: { isLoading } } = useForm({ mode: 'onBlur', defaultValues: async () => fetchData(id), }) // 渲染表单前先判断加载状态 if (isLoading) { return <div>加载中...</div> } // 再渲染完整表单内容
3. 统一数据类型(可选)
如果不想在Controller中转类型,也可以在fetchData里直接把gender转为字符串:
async function fetchData(id) { // ...原有逻辑 data.gender = data.gender.toString() return data }
这样表单中的gender会和SelectItem的value保持类型一致,无需额外转换。
额外说明
- 不要手动设置
defaultSelectedKeys,react-hooks-form的表单状态应由Controller或register统一管理,手动设置会导致状态不一致。 - 异步
defaultValues加载完成后,react-hooks-form会自动更新表单状态,通过Controller绑定后就能同步到Select组件上。
内容的提问来源于stack exchange,提问作者Lansheng
相关产品推荐
相关产品推荐

