MaterialUI Autocomplete开启multiple时getOptionSelected误选问题
问题场景
使用Material UI 4.x版本(具体版本:@material-ui/core": "^4.9.12", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", "@material-ui/pickers": "^3.2.10", "@material-ui/styles": "^4.9.10)的Autocomplete组件,开启multiple模式,绑定字符串数组enabledTeams作为value和options。添加getOptionSelected属性后,点击取消某选中选项时,被移除的总是第一个选中项;移除该属性后功能恢复正常。
原因
getOptionSelected的核心作用是判断选项数组中的单个项与选中值数组中的单个项是否匹配,它的标准参数是(option, value):
option:遍历options数组时的当前项value:遍历选中value数组时的当前项
你写的getOptionSelected={(option) => enabledTeams.includes(option)}逻辑完全错误:这个写法会返回true只要当前option存在于整个enabledTeams数组中,当组件要定位你点击的待移除项时,会匹配到第一个满足条件的项(也就是数组第一项),所以每次都会删掉第一个选中项。
另外,对于字符串这种原始类型,Material UI默认的getOptionSelected逻辑就是(option, value) => option === value,完全覆盖你的场景,这也是移除该属性后功能正常的原因。
解决办法
- 最优方案:直接移除
getOptionSelected属性,依赖组件默认的全等比较逻辑即可,完全满足字符串数组的匹配需求。 - 如果后续有类型变更等特殊需求需要手动指定,使用正确的参数和逻辑:
getOptionSelected={(option, value) => option === value}
修正后的完整代码示例
<Autocomplete freeSolo multiple value={enabledTeams} options={enabledTeams} getOptionLabel={(option) => option} renderInput={(params) => ( <TextField type="search" {...params} label="Label" helperText="Some text" /> )} onChange={(e, v) => setEnabledTeams(v)} />
内容的提问来源于stack exchange,提问作者Leonard Kee

