Formik SetField无法更新数组值,Material UI Autocomplete初始化异常
我从API获取的数据格式为otherLanguages:[{code:EN,name:"English"},{code:MD,name:"Mandarin"}],尝试将其赋值给Formik的initialValues来初始化Material UI Autocomplete组件。但发现该组件似乎仅接受[{value:"EN",label:"English"},{value:"MD",label:"Mandarin"}]格式的数据,请问是否需要转换数据格式?另外配置如下Autocomplete组件后,初始值始终无法更新,从Formik初始状态设置组件值时还会报错,尝试处理事件也无效果:
<Autocomplete getOptionLabel={(option: { label: any; }) => option.label} getOptionSelected={(option: { title: string; }) => option.title === 'dull'} id="tags-standard" multiple onChange={(e)=>{console.log(e.target)}} options={countryLanguages} popupIcon={<ExpandMoreIcon />} renderInput={(params: any) => ( <> <Label color={Colors.Grey900} fontSize="16px" value="Other Languages"/> <StyledTextField {...params} InputProps={{ ...params.InputProps, endAdornment: ( <InputAdornment position="start"></InputAdornment> ) }} variant="standard" /> </> )} value={formik.values.otherLanguages} />
一、数据格式处理:无需强制转换,适配即可
Material UI Autocomplete并不强制要求选项必须是{value, label}格式,只要通过getOptionLabel和getOptionSelected两个属性正确映射你的数据字段就行:
getOptionLabel:用来指定选项显示的文本,对应你的name字段getOptionSelected:用来判断选中项与选项是否匹配,对应你的唯一标识code字段
如果你偏好统一成{value, label}格式,也可以提前转换数据:
// 转换API返回的数据 const convertedLanguages = otherLanguages.map(item => ({ value: item.code, label: item.name }));
转换后直接用这个数组作为options,同时Formik的initialValues.otherLanguages也要用转换后的格式(比如[{value: 'EN', label: 'English'}])。
二、修复Autocomplete组件的配置问题
你的组件有几个关键错误导致初始值失效、报错和事件无响应,逐个修正:
修正
getOptionLabel和getOptionSelected
这两个函数的参数类型和逻辑完全错误,改成和你的数据结构匹配:getOptionLabel={(option) => option.name} // 用name作为显示文本 getOptionSelected={(option, selectedOption) => option.code === selectedOption.code} // 用code判断选项是否匹配修正
onChange事件,同步Formik状态
Autocomplete的onChange参数是(event, newValue),不是普通的input事件,需要手动调用Formik的setFieldValue来更新状态:onChange={(e, newValue) => { formik.setFieldValue('otherLanguages', newValue); }}确保Formik初始值格式正确
因为组件是multiple多选模式,initialValues.otherLanguages必须是数组,且数组项的格式要和options一致:// Formik的initialValues示例 initialValues: { otherLanguages: [] // 空数组表示初始无选中,或者放API返回的特定项比如[{code: 'EN', name: 'English'}] }移除错误的InputProps覆盖
你覆盖了params.InputProps.endAdornment为空,这会导致Autocomplete的默认下拉图标失效,直接去掉这个覆盖即可:<StyledTextField {...params} variant="standard" />
修正后的完整组件代码
<Autocomplete getOptionLabel={(option) => option.name} getOptionSelected={(option, selectedOption) => option.code === selectedOption.code} id="tags-standard" multiple onChange={(e, newValue) => formik.setFieldValue('otherLanguages', newValue)} options={countryLanguages} popupIcon={<ExpandMoreIcon />} renderInput={(params) => ( <> <Label color={Colors.Grey900} fontSize="16px" value="Other Languages" /> <StyledTextField {...params} variant="standard" /> </> )} value={formik.values.otherLanguages} />
内容的提问来源于stack exchange,提问作者SilverRetriever

