React Hook Form结合Material UI异步Select组件默认值不选中问题解决
解决React Hook Form + Material UI下拉框初始不选中已保存值的问题
问题根源分析
你的代码存在几个关键问题导致初始选中失败:
- 异步默认值处理错误:
useForm的defaultValues直接传入了异步函数fetchDetails,react-hook-form无法直接解析异步函数作为默认值。 - Select的onChange覆盖问题:自定义的
onCountryChange覆盖了field.onChange,导致表单状态无法同步更新。 - 数据加载顺序问题:保存的详情和国家列表可能异步加载顺序不一致,导致设置初始值时对应的选项还未渲染。
具体修复步骤
1. 修正表单默认值的异步初始化
移除useForm中defaultValues的异步函数,改用useEffect在组件挂载后获取数据并重置表单:
const { control, setValue, formState: { errors }, watch, trigger, getValues, reset, setError, } = useForm<FormDataType>({ resolver: yupResolver(schema), defaultValues: { email: '', country: '', // 其他字段设置对应初始空值 }, shouldFocusError: true, mode: 'all', }); // 加载初始保存值并重置表单 useEffect(() => { const loadInitialData = async () => { const savedValues = await fetchDetails(); reset(savedValues); }; loadInitialData(); }, [fetchDetails, reset]);
2. 同步Select的onChange与表单状态
不要直接覆盖field.onChange,在自定义的onCountryChange中调用它,确保表单状态同步:
// 调整onCountryChange函数 const onCountryChange = (event) => { // 这里保留你的自定义逻辑(比如联动其他字段等) field.onChange(event.target.value); // 必须调用这个来更新react-hook-form的状态 }; // 在Select组件中使用 <Select id="country" label="country" aria-label="country" required displayEmpty MenuProps={{ sx: { maxHeight: 200 } }} {...field} error={!!errors?.country?.message} helperText={errors?.country?.message} onChange={onCountryChange} >
如果自定义逻辑简单,也可以直接内联处理:
onChange={(event) => { field.onChange(event.target.value); // 你的自定义逻辑代码 }}
3. 确保值与选项的类型匹配
检查fetchDetails返回的country值,和countryList中country.value的类型完全一致(比如都是字符串,不能一个是数字一个是字符串)。如果类型不匹配,会导致无法匹配选项。
4. 处理国家列表加载延迟的情况
如果保存的国家值先加载完成,但国家列表还未渲染,会导致找不到对应选项。可以监听countryList的变化,验证初始值的有效性:
useEffect(() => { if (countryList?.length) { const currentCountry = getValues('country'); const isValidCountry = countryList.some(item => item.value === currentCountry); if (!isValidCountry && currentCountry) { // 如果保存的国家不在列表中,重置为空值 setValue('country', ''); } } }, [countryList, getValues, setValue]);
内容的提问来源于stack exchange,提问作者Khushi
相关产品推荐
相关产品推荐

