Из существующих данных я динамически генерирую ряд элементов MUI "<Select>". Однако при взаимодействии с одним из элементов «<Select>» выбранное значение применяется ко всем элементам «<Select>».
Например, это данные:
const groups = [{name: "group1",group_id: 1}, {name: "group2", group_id: 2}];
const options = [
{name: "option1", option_id: 1, group_id: 1},
{name: "option2", option_id: 2, group_id: 1},
{name: "option3", option_id: 3, group_id: 1},
{name: "option4", option_id: 4, group_id: 2},
{name: "option5", option_id: 5, group_id: 2},
{name: "option6", option_id: 6, group_id: 2},
]
Используя эти данные, создаются два элемента "<Select>". Каждый имеет различные 3 варианта. Когда я выбираю с помощью первого элемента "<Select>", значение во втором элементе "<Select>" также изменяется.
Мой код для генерации элементов:
const [selectedElements, setSelectedElements] = React.useState([]);
const onSelectionChange = (event, serviceGroup) => {
const value = event.target.value;
setSelectedElements(
typeof value === 'string' ? value.split(',') : value,
);
}
return (
<div>
{
groups.map(function(group) {
return (
<Select
multiple
value = {selectedElements}
onChange = {(e)=>onSelectionChange(e, group)}
id = {group.group_id}
renderValue = {(selected) => selected.join(', ')}
>
{
options.map(function (option) {
if (option.group_id === group.group_id) {
return (
<MenuItem
key = {option.option_id}
value = {option.name}
>
<ListItemText primary = {option.name} />
<Checkbox checked = {selectedElements.indexOf(option.name) > -1}/>
</MenuItem>
)
}
})
}
</Select>
)
})
}
</div>
)
Я знаю, что "value = {selectedElements}" приведет к тому, что каждый динамически сгенерированный элемент "<Select>" будет иметь одинаковое значение, поэтому, если один из них изменит свое значение, другие тоже изменят свое значение.
Чтобы исправить это, я попытался использовать const [selectedElementsObj, setSelectedElementsObj] = React.useState({});
— состояние объекта, а затем заменить «value = {selectedElements}» на «value = {selectedElementsObj[group.name]}».
Находясь внутри функции onSelectionChange, я создал объект массивов, так что внутри selectedElementsObj у меня будет отдельный массив для каждого элемента "<Select":
const objCopy = Object.assign({}, selectedElementsObj);
objCopy[group.name] = typeof value === 'string' ? value.split(',') : value;
setSelectedElementsObj(objCopy);
Проблема с моей попыткой заключается в том, что она просто не отображается, и я получаю белый экран. Надеюсь, я ясно описал свою проблему, и вот кодыпесочница с примером, который я показал здесь!
Проблема здесь в том, что в событии onChange вы не устанавливали значение для этого конкретного элемента (как вы также сказали). Таким образом, чтобы идентифицировать каждый элемент по-разному, должен быть определенный ключ в selectedElements
или selectedElementsObj
, на основе которого мы можем знать, что это значение должно быть установлено для этого определенного идентификатора.
Чтобы решить эту проблему, я установил seletedElements
с массивом групп объектов.
const [selectedElements, setSelectedElements] = React.useState(groups);
А затем использовал это для сопоставления компонента Select и изменил его значение на основе значения selectedElements.
selectedElements.map(function (group) {
return (
<Select
style = {{ marginBottom: "10px" }}
multiple
value = {group?.value || []}
onChange = {(e) => onSelectionChange(e, group)}
id = {group.group_id}
renderValue = {(selected) => selected.join(", ")}
sx = {{
"& legend": { display: "none" },
"& fieldset": { top: 0 }
}}
>
{options.map(function (option) {
if (option.group_id === group.group_id) {
return (
<MenuItem key = {option.option_id} value = {option.name}>
<ListItemText primary = {option.name} />
<Checkbox
checked = {selectedElements.indexOf(option.name) > -1}
/>
</MenuItem>
);
}
})}
</Select>
);
})}
И последней оставшейся частью было присвоение (а не создание здесь) этого значения в этом объекте, для которого я сделал это внутри вызова функции onChange:
selectedElements.map(item => {
if (item.group_id === group.group_id)
{
item.value = typeof value === "string" ? value.split(",") : value
}
})