MUI Select结合react-hook-form设置defaultValue后无法修改值
问题根因
问题出在值类型不匹配:
- 你给Controller配置的
defaultValue是空字符串"",属于基础类型 - 但Select的MenuItem绑定的
value是整个对象类型
MUI Select内部通过严格相等(===)判断选中项,空字符串和任何对象都不可能相等,所以选中状态无法正常渲染更新。另外你的代码还有两个隐藏问题:一是错误状态读取用错了字段名,二是自定义了完全没被调用的handleChange逻辑,属于冗余代码。
修复步骤
- 修正Controller的默认值类型:初始无选中项时不要用空字符串作为默认值,改用
null,和后续选中的对象类型保持兼容。 - 给Select的值加空态兜底:未选中时把value fallback为空字符串,适配MUI InputLabel的浮动逻辑,避免label和选中值重叠。
- 修正错误状态读取逻辑:Controller绑定的表单字段名是
formname,读取errors时也要用这个字段名,之前用name会导致校验错误无法正常显示。 - (推荐)统一配置表单默认值:不要在单个Controller上配置defaultValue,把所有字段的初始值统一放到
useForm初始化的defaultValues参数里,这样调用reset方法时能正常重置,也不会出现字段值联动异常。
修复后核心代码
function MySelect({ formname, name, setSelected, data = [] }) { const { control, formState: { errors }, watch } = useFormContext(); // 如果需要同步选中值到外部,直接用watch监听对应字段即可 const selectedValue = watch(formname); React.useEffect(() => { if (setSelected) setSelected(selectedValue); }, [selectedValue, setSelected]); return ( <Box sx={{minWidth: 120}}> <InputLabel id="demo-multiple-name-label">{name}</InputLabel> <Controller name={formname} control={control} // 如果已经在useForm里配置了defaultValues,这里可以删掉defaultValue配置 defaultValue={null} render={({ field: { onChange, value } }) => ( <Select sx={{ width: 200 }} labelId="demo-multiple-name-label" id="demo-multiple-name" multiple={false} value={value ?? ''} onChange={onChange} input={<OutlinedInput label={name} />} MenuProps={MenuProps} error={!!errors[formname]} helperText={errors[formname]?.message || ''} > {data.map((element, i) => { if (element.bsa_maskenkey) return ( <MenuItem value={element} key={i}> {`${element.bsa_maskenkey} ${element.we_menge}`} </MenuItem> ); else if (element.blager_maskenkey) return ( <MenuItem value={element} key={i}> {`${element.blager_maskenkey} ${element.blagerpo_maskenkey} | Menge: ${element.summe}`} </MenuItem> ); else return ( <MenuItem value={element} key={i}> {`${element.objekt} | Menge: ${element.menge}`} </MenuItem> ); })} </Select> )} /> </Box> ); }
外层useForm配置参考:
const methods = useForm({ defaultValues: { // 对应传入MySelect的formname字段,初始值设为null // 其他表单字段也在这里统一配置初始值 } });
内容的提问来源于stack exchange,提问作者Nicklas Desens
相关产品推荐
相关产品推荐

