Как я могу динамически генерировать несколько элементов MUI Select и их параметры?

Из существующих данных я динамически генерирую ряд элементов 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);

Проблема с моей попыткой заключается в том, что она просто не отображается, и я получаю белый экран. Надеюсь, я ясно описал свою проблему, и вот кодыпесочница с примером, который я показал здесь!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
48
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема здесь в том, что в событии 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
  }
})

Другие вопросы по теме