Material UI Select在React Hook Form中初始默认值不显示问题
问题解决思路及方案
核心问题分析
初始页面刷新时,Redux中的defaultTemplates可能还未加载完成,导致defaultTemplate为undefined;而React Hook Form的defaultValues仅在组件初始化时生效一次,后续Redux数据更新后不会自动同步到表单默认值。即使后续defaultTemplate获取到有效值,表单也不会重新初始化,因此初始渲染时Select组件无法显示默认值;而切换页面返回时,Redux数据已加载完成,表单重新初始化后才能正常显示默认值。
具体修复步骤
1. 监听数据加载完成后同步表单默认值
使用useEffect监听defaultTemplates的变化,当数据就绪后调用reset方法更新表单值,确保表单能获取到正确的默认值:
const { control, reset } = useForm<IFormInput>({ defaultValues: { templateType: undefined // 初始设为undefined,避免无效值 } }); useEffect(() => { if (defaultTemplates?.length) { const assignedTemplate = createTenant?.quota?.selected_template || 'Small'; const defaultTemplate = defaultTemplates.find(template => template.template_name === assignedTemplate); reset({ templateType: defaultTemplate }); } }, [defaultTemplates, createTenant, reset]);
2. 优化Select组件的value处理逻辑
给Controller显式设置defaultValue,同时完善renderValue的空值处理,避免渲染异常:
<Controller name={name} control={control} defaultValue={undefined} render={({ field }) => ( <Select fullWidth {...field} onChange={(e) => field.onChange(e.target.value)} renderValue={(selected) => { if (!selected) return ''; // 处理selected为undefined的情况 return dropDownOptionKey ? selected[dropDownOptionKey] : selected; }} > {generateSingleOptions()} </Select> )} />
3. 修复MenuItem的key值问题
避免使用index作为MenuItem的key,改用数据中的唯一标识(如template_name),确保组件渲染的稳定性:
const generateSingleOptions = () => { return dropDownOptions?.map((option: any) => ( <MenuItem key={option.template_name} value={option}> {dropDownOptionKey ? option[dropDownOptionKey] : option} </MenuItem> )); };
完整修复后的代码片段
FormInputDropDown组件
const FormInputDropDown: React.FC<FormInputProps> = ({ name, control, handleDropDownChange, dropDownOptionKey, dropDownOptions }) => { const generateSingleOptions = () => { return dropDownOptions?.map((option: any) => ( <MenuItem key={option.template_name} value={option}> {dropDownOptionKey ? option[dropDownOptionKey] : option} </MenuItem> )); }; return ( <Controller name={name} control={control} defaultValue={undefined} render={({ field }) => ( <Select fullWidth {...field} onChange={(e) => field.onChange(e.target.value)} renderValue={(selected) => { if (!selected) return ''; return dropDownOptionKey ? selected[dropDownOptionKey] : selected; }} > {generateSingleOptions()} </Select> )} /> ); }; export default FormInputDropDown;
表单使用部分
interface IFormInput { templateType: TenantTemplate | undefined; } const createTenant = useSelector((state: RootState) => state.createTenant); const defaultTemplates = useSelector((state: RootState) => state.buTemplates.templates); const { control, reset } = useForm<IFormInput>({ defaultValues: { templateType: undefined } }); useEffect(() => { if (defaultTemplates?.length) { const assignedTemplate = createTenant?.quota?.selected_template || 'Small'; const defaultTemplate = defaultTemplates.find(template => template.template_name === assignedTemplate); reset({ templateType: defaultTemplate }); } }, [defaultTemplates, createTenant, reset]); <FormInputDropDown name="templateType" control={control} dropDownOptions={defaultTemplates || []} dropDownOptionKey="template_name" />
内容的提问来源于stack exchange,提问作者Saksham Singh
相关产品推荐
相关产品推荐

