MUI v5 Select组件重复选项多选异常问题处理咨询
MUI v5 解决多选Select组件重复选项选中问题
问题说明
使用MUI v5的多选Select组件时,若存在名称重复的选项,选择其中一个会导致所有同名选项被同时选中。这是因为当前代码使用**名称(name)**作为选项的value,而重复的名称无法被组件区分。
原代码
import * as React from "react"; import OutlinedInput from "@mui/material/OutlinedInput"; import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import FormControl from "@mui/material/FormControl"; import ListItemText from "@mui/material/ListItemText"; import Select, { SelectChangeEvent } from "@mui/material/Select"; import Checkbox from "@mui/material/Checkbox"; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { style: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250 } } }; const namesObj = [ { id: 1, name: "Oliver Hansen" }, { id: 2, name: "Van Henry" }, { id: 3, name: "April Tucker" }, { id: 4, name: "April Tucker" } ]; export default function MultipleSelectCheckmarks() { const [personName, setPersonName] = React.useState<string[]>([]); console.log("personName: ", personName); const handleChange = (event: SelectChangeEvent<typeof personName>) => { const { target: { value } } = event; setPersonName( // On autofill we get a stringified value. typeof value === "string" ? value.split(",") : value ); }; return ( <div> <FormControl sx={{ m: 1, width: 300 }}> <InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel> <Select labelId="demo-multiple-checkbox-label" id="demo-multiple-checkbox" multiple value={personName} onChange={handleChange} input={<OutlinedInput label="Tag" />} renderValue={(selected) => selected.join(", ")} MenuProps={MenuProps} > {namesObj.map((name) => ( <MenuItem key={name.id} value={name.name}> <Checkbox checked={personName.indexOf(name.name) > -1} /> <ListItemText primary={name.name} /> </MenuItem> ))} </Select> </FormControl> </div> ); }
解决方案
核心思路是使用**唯一标识(id)**作为选项的value,而非重复的名称,让组件能精准区分每个选项。具体修改点如下:
- 状态类型调整:将存储选中项的变量从
string[]改为number[],存储选中项的id而非名称 - 选项值替换:
MenuItem的value从name.name改为name.id - 选中状态判断:Checkbox的
checked逻辑改为检查当前id是否在选中数组中 - 显示值映射:
renderValue方法将选中的id转换为对应的名称,保持界面显示不变 - 事件处理调整:确保
handleChange中处理的是id数组
修改后的完整代码
import * as React from "react"; import OutlinedInput from "@mui/material/OutlinedInput"; import InputLabel from "@mui/material/InputLabel"; import MenuItem from "@mui/material/MenuItem"; import FormControl from "@mui/material/FormControl"; import ListItemText from "@mui/material/ListItemText"; import Select, { SelectChangeEvent } from "@mui/material/Select"; import Checkbox from "@mui/material/Checkbox"; const ITEM_HEIGHT = 48; const ITEM_PADDING_TOP = 8; const MenuProps = { PaperProps: { style: { maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, width: 250 } } }; const namesObj = [ { id: 1, name: "Oliver Hansen" }, { id: 2, name: "Van Henry" }, { id: 3, name: "April Tucker" }, { id: 4, name: "April Tucker" } ]; export default function MultipleSelectCheckmarks() { // 存储选中项的id,类型改为number数组 const [selectedIds, setSelectedIds] = React.useState<number[]>([]); console.log("selectedIds: ", selectedIds); const handleChange = (event: SelectChangeEvent<typeof selectedIds>) => { const { target: { value } } = event; setSelectedIds( typeof value === "string" ? value.split(",").map(Number) : value ); }; // 根据id获取对应的名称,用于显示 const getSelectedNames = () => { return selectedIds.map(id => { const item = namesObj.find(item => item.id === id); return item ? item.name : ""; }).join(", "); }; return ( <div> <FormControl sx={{ m: 1, width: 300 }}> <InputLabel id="demo-multiple-checkbox-label">Tag</InputLabel> <Select labelId="demo-multiple-checkbox-label" id="demo-multiple-checkbox" multiple value={selectedIds} onChange={handleChange} input={<OutlinedInput label="Tag" />} renderValue={getSelectedNames} MenuProps={MenuProps} > {namesObj.map((item) => ( <MenuItem key={item.id} value={item.id}> <Checkbox checked={selectedIds.includes(item.id)} /> <ListItemText primary={item.name} /> </MenuItem> ))} </Select> </FormControl> </div> ); }
说明
修改后,组件通过唯一id识别每个选项,即使名称重复也能独立选中/取消选中。界面上依然显示选项名称,但实际存储的是唯一id,避免了重复值导致的选中异常。
内容的提问来源于stack exchange,提问作者asus
相关产品推荐
相关产品推荐

