Как правильно переписать состояние в фильтрах React

avatar
Festina
9 августа 2021 в 06:19
76
2
1

Мне нужно использовать входной фильтр в React. У меня есть список действий, и мне нужно отфильтровать их, как фильтры на картинке. Если значки не отмечены, действия с этими типами действий не должны отображаться. Это работает.

Проблема в том, что когда я использую входной фильтр и пишу буквы, он работает. Но когда я удаляю букву за буквой, ничего не меняется.

Я понимаю, что проблема в том, что я записываю результат в состояние. И состояние изменено. Но как его правильно переписать. filter example

const [activities, setActivities] = useState(allActivities);
  const [value, setValue] = useState(1);
  const [checked, setChecked] = useState<string[]>([]);

  const switchType = (event: React.ChangeEvent<HTMLInputElement>)=> {
    const currentIndex = checked.indexOf(event.target.value);
    const newChecked = [...checked];

    if (currentIndex === -1) {
      newChecked.push(event.target.value);
    } else {
      newChecked.splice(currentIndex, 1);
    }

//function that shows activities if they are checked or unchecked
    
setChecked(newChecked);

    const res = allActivities.filter(({ type }) => !newChecked.includes(type));
    setActivities(res);
  };
//shows input filter
  const inputSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
    
    const foundItems = activities.filter(
      (item) => item.activity.indexOf(event.target.value) > -1
    );

    setActivities(foundItems);
  };
//shows participants filter
  const countSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
    setValue(Number(event.target.value));
    const participantsSearch = allActivities.filter(
      (item) => item.participants >= event.target.value
    );
    setActivities(participantsSearch);
  };

Это часть визуализации

  <Input
            onChange={inputSearch}       
               startAdornment={
              <InputAdornment position="start">
                <SearchIcon />
              </InputAdornment>
            }
          />
 <Input
            onChange={countSearch}
            type="number"
            value={props.value}
                      startAdornment={
              <InputAdornment
                position="start"
                className={classes.participantsTextField}
              >
                <PersonIcon />
              </InputAdornment>
            }
          />
Источник

Ответы (2)

avatar
Drew Reese
9 августа 2021 в 07:26
1

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

Кроме того, из-за того, как вы написали флажок и обратные вызовы ввода, вы не можете легко смешать их.

Поскольку отфильтрованные данные по существу являются "производным" состоянием из реквизита allActivities и состояний value и checked, их действительно не следует хранить в состоянии. Вы можете фильтровать allActivities во время рендеринга.

const [value, setValue] = useState<sting>('');
const [checked, setChecked] = useState<string[]>([]);

const switchType = (event: React.ChangeEvent<HTMLInputElement>)=> {
  const currentIndex = checked.indexOf(event.target.value);

  if (currentIndex === -1) {
    setChecked(checked => [...checked, event.target.value]);
  } else {
    setChecked(checked => checked.filter((el, i) => i !== currentIndex);
  }
};

const inputSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
  setValue(event.target.value.toLowerCase());
};

...

return (
  ...

  {allActivites.filter(({ activity, type }) => {
      if (activity || type) {
        if (type) {
          return checked.includes(type);
        }
        if (activity) {
          return activity.toLowerCase().includes(value);
        }
      }
      return true; // return all
    })
    .map(.....
avatar
Roi
9 августа 2021 в 07:18
0

Проблема связана с вашим кодом inputSearch. Каждый раз, когда вы делаете setActivities(foundItems);, вы сужаете состояние своего списка activities. Поэтому, когда вы начнете удаление, вы не увидите никаких изменений, потому что вы удалили остальные действия из состояния.

Вы хотите вывести allActivities в константу и всегда фильтровать allActivities в inputSearch, например:

const allActivities = ['aero', 'aeroba', 'aerona', 'aeronau'];
const [activities, setActivities] = useState(allActivities);

// ...rest of your code

const inputSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
  const foundItems = allActivities.filter(
    (item) => item.activity.indexOf(event.target.value) > -1
  );
  setActivities(foundItems);
};
// ...rest of your code
Festina
9 августа 2021 в 08:13
0

Я согласен с этим вариантом, но в этом варианте мы фильтруем все действия. И мне нужно отфильтровать те, которые были выбраны после фильтра флажка. Другими словами, все фильтры подключены. Если я выбираю спортивные и социальные мероприятия, входной фильтр должен отображать действия с этим типом, но не все.