ReactJS — фильтрация элементов из списка в раскрывающемся списке выбора

#javascript #arrays #reactjs

#javascript #массивы #reactjs

Вопрос:

В настоящее время я пытаюсь отфильтровать существующий список элементов по выбранным в раскрывающемся списке выбора. Это означает, что всякий раз, когда я нажимаю на элемент, я хочу удалить его из доступных опций (поэтому я не могу добавить его дважды в список).

Проблема, с которой я сталкиваюсь, заключается в том, что всякий раз, когда я отфильтровываю этот элемент, я не отображаю его на экране (потому что я удалил его из списка). Как я могу удалить элемент из списка доступных опций, но при этом отобразить его на экране? Также, если я решу снова изменить элемент, будет ли предыдущий отображаться в списке снова?

Я подозреваю, что проблема может быть в моей функции фильтрации:

   const filterElements = (selectedPerson) => {
    let filteredList = people.filter((person) => {
      return selectedPerson.id !== person.id;
    });
    setPeople(filteredList);
  };
 

Вот небольшая программная среда, которую я создал в качестве примера.

Ответ №1:

Я бы посоветовал вам попытаться объяснить проблему немного лучше: возможно, я не понял правильно, но вот мое решение.

Похоже, вы всегда хотите показывать все параметры в раскрывающемся списке, даже если они уже выбраны. Для этого просто сохраните список всех параметров и отобразите каждый из них в пользовательском интерфейсе, даже если они уже были выбраны (отфильтрованы) пользователем. Попробуйте это:

 const allPeople = [
    { id: 1, name: "Mark" },
    { id: 2, name: "Peter" },
    { id: 3, name: "John" },
    { id: 4, name: "David" },
    { id: 5, name: " Karen" },
    { id: 6, name: "Johanes" }
]

const [people, setPeople] = useState(allPeople);

const renderOptions = () =>
    allPeople.map((person) => {  //... your UI));
});
 

Ответ №2:

Кажется, вы хотите отфильтровать уже выбранные варианты из других входных данных, но не те входные данные, для которых уже выбран данный выбор.

Вы можете сделать это filterElements , полностью удалив функцию и изменив свою renderOptions функцию так, чтобы она возвращала только те параметры, которые в данный момент не выбраны (если не выбраны текущим вводом).

Вот как renderedOptions может выглядеть:

 const renderOptions = (selected) => {
  const filteredPeople = people.filter(e => e.name === selected || ![selectedOne, selectedTwo, selectedThree].includes(e.name));
  return filteredPeople.map((person) => {
    return (
      <MenuItem value={person.name}>
        {person.name}
      </MenuItem>
    );
  });
}
 

Первое условие в filter обратном вызове проверяет, выбран ли параметр этим вводом, и включает параметр, если это так, второе условие проверяет, выбран ли параметр любым вводом, и удаляет параметр, если это так. Все остальные параметры будут включены.

Затем вызывайте renderOptions так:

 <Select
  name="name"
  value={selectedOne}
  onChange={(e) => setSelectedOne(e.target.value)}
  input={<Input id="name" />}
>
  {renderOptions(selectedOne)}
</Select>
<Select
  name="name"
  value={selectedTwo}
  onChange={(e) => setSelectedTwo(e.target.value)}
  input={<Input id="name" />}
>
  {renderOptions(selectedTwo)}
</Select>
<Select
  name="name"
  value={selectedThree}
  onChange={(e) => setSelectedThree(e.target.value)}
  input={<Input id="name" />}
>
  {renderOptions(selectedThree)}
</Select>
``

This way the selected options aren't removed entirely, just hidden from those inputs that should not have access to them.
 

Комментарии:

1. Я видел, что внутри вы выполняете фильтрацию по имени , как в e.name === selected . Что, если у меня есть больше полей с одинаковым именем, я бы предпочел, чтобы мы фильтровали по идентификатору.

2. @ZombieChowder Я только что сделал это, потому что ваша программа устанавливает значения selectedX для person name , если вы хотите использовать id вместо этого, просто замените name с id в filter вызове и измените value of MenuItem с person.name на person.id .

Ответ №3:

Было бы проще добавить isVisible флаг свойства для каждого пользователя и вместо фильтрации просто обновить выбранного пользователя с помощью isVisible = false

   const [people, setPeople] = useState([
    { id: 1, name: "Mark", isVisible: true },
    { id: 2, name: "Peter", isVisible: true },
    { id: 3, name: "John", isVisible: true },
    { id: 4, name: "David", isVisible: true },
    { id: 5, name: " Karen", isVisible: true },
    { id: 6, name: "Johanes", isVisible: true }
  ]);

  const filterElements = (selectedPerson) => {
    const index = people.findIndex(p => p.id === selectedPerson.id);
    selectedPerson[index].isVisible = false;
    setPeople(selectedPerson);
  };
 

и здесь просто сделайте:

 const renderOptions = () =>
  people.filter(p => p.isVisible).map((person) => {
    return (
      <MenuItem value={person.name} onClick={() => filterElements(person)}>
        {person.name}
      </MenuItem>
    );
 });