If you specified both getOptionLabel and renderOption, and convert it to label the same way, MUI takes care of all the items. However, when duplicated item/label exist and I type in some characters, it’ll keep bringing in the one with the exact same label. This also creates an error in selecting an item. In real life, users are allowed to have multiple accounts. People with identical names do exist. So I should say it is an MUI bug. A workaround is to provide a different label as the following example.
import React, { useState } from 'react';
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
let userList = [
{ id: 1, name: "John Public" },
{ id: 2, name: "John Public" },// duplicated item
{ id: 3, name: "John Wicky" },
{ id: 4, name: "Emma Fullman" },
{ id: 5, name: "Nicolas Kage" },
{ id: 6, name: "John Wicky" }, // duplicated item
{ id: 7, name: "Emily Simpleton" },
{ id: 8, name: "Zoe Simpleton" },
{ id: 9, name: "John Wicky" }, // another duplicated item
];
// sort by name
userList = userList.sort((uA, uB) => uA.name.localeCompare(uB.name));
// use filter function but not to eliminate any items
userList = userList.filter((uList, index) => {
// check if user has the same name/label
if (index !== userList.findIndex(tList => uList.name === tList.name)) {
// add the ID value at the end of name/label
userList[index].name += " (" + uList.id + ")";
}
return true;
});
// Or you can add an identifier instead of ID. NOTE: sorting must be done first.
let duped = 0;
userList = userList.filter((uList, index) => {
// check if user has the same name/label
if (index !== userList.findIndex(tList => uList.name === tList.name)) {
duped++;
// add an identifier at the end of name/label
userList[index].name += " (Duplicated # " + duped + ")";
}
else {
duped = 0;
}
return true;
});
export default function Tags() {
const [selected, setSelected] = useState([]);
return (
<Autocomplete
value={selected}
options={userList}
onChange={(_, newUsers) => setSelected(newUsers)}
getOptionLabel={(option) => option.name}
renderInput={(params) => <TextField {...params} label="Users" />}
/>
);
}
The result screen looks like:
