MUI V5类组件自定义Autocomplete支持新增输入及显示问题修复
问题根因
MUI v5对Autocomplete组件的API做了两处不兼容调整,直接导致你遇到的两个问题:
renderOption属性的入参顺序变化:v4直接传入option对象,v5第一个参数是li元素的属性对象,第二个参数才是option对象,你现有代码拿不到正确的option值,所以新增选项提示无法显示- 未配置
isOptionEqualToValue默认逻辑:v5默认用对象严格相等判断选中值和选项的匹配关系,如果选中值和options数组里的对应项不是同一个引用,就会匹配失败,导致初始加载显示为空
修复代码
1. 自定义SingleSoloSelect2组件修改
import React from 'react'; import TextField from '@mui/material/TextField'; import Autocomplete from '@mui/material/Autocomplete'; const SingleSoloSelect2 = (props) => { const filter = (options, params) => { let inList = false; const filtered = options.filter(o => { if (!params.inputValue) return true; const value = o[props.labelField].toLowerCase(); const input = params.inputValue.toLowerCase(); if (value === input) inList = true; if (value.includes(input)) return true; return false; }); return { inList, filtered }; } return ( <Autocomplete fullWidth freeSolo={props.freeSolo ?? true} id={props.id} value={props.value} options={props.options || []} disabled={props.disabled} selectOnFocus clearOnBlur handleHomeEndKeys onChange={(e, v) => { let isNew = false; if (typeof v === 'string') { // 兼容v5 freeSolo模式返回字符串的情况,转成统一对象格式 v = { [props.valueField]: v, [props.labelField]: v, new: true } isNew = true; } else if (v?.new) { isNew = true; } props.onChange(v, isNew, props.id); }} getOptionLabel={props.getOptionLabel ?? ((option) => option?.[props.labelField] ?? '')} filterOptions={(options, params) => { const { inList, filtered } = filter(options, params); if ((props.freeSolo ?? true) && params.inputValue !== '' && !inList) { filtered.push({ [props.valueField]: params.inputValue, [props.labelField]: params.inputValue, new: true, }); } return filtered; }} // 修复入参顺序,第一个是li的属性参数,避免和组件props重名 renderOption={(liProps, option) => { return ( <li {...liProps}> {option.new ? `新增 "${option[props.labelField]}"` : option[props.labelField]} </li> ) }} // 增加默认匹配逻辑,解决初始值匹配失败为空的问题 isOptionEqualToValue={props.isOptionEqualToValue ?? ((option, value) => { return option?.[props.valueField] === value?.[props.valueField] })} renderInput={(params) => (<TextField {...params} label={props.label} variant={props.variant} size={props.size} error={props.error} />)} /> ); } export default SingleSoloSelect2;
2. handleSingleSelect逻辑优化(可选)
handleSingleSelect = (v, isNew) => { // 避免直接修改state,符合React immutable规范 const q = {...this.state.activeQuestion}; q.value = v; if (isNew) { // 去掉new标记再存到options,避免后续选项里显示新增标识 const newOption = {...v}; delete newOption.new; q.options.push(newOption); } this.setState({ activeQuestion: q }); }
额外调整说明
- 修复了freeSolo默认值的判断,用空值合并运算符
??替代原来的三元判断,更简洁 - 修正了onChange里新值的处理逻辑,统一转成对象格式,避免后续业务逻辑同时处理字符串和对象两种格式
- 增加了getOptionLabel的默认值,不传的话也可以根据labelField自动读取,减少调用时的重复代码
内容的提问来源于stack exchange,提问作者Jetro Olowole
相关产品推荐
相关产品推荐

