ReactJS пытается создать список фильтров

#javascript #reactjs

#javascript #reactjs

Вопрос:

Я пытаюсь создать список фильтров, который фильтрует список по введенному вводу. Но не знаю, почему оператор if не работает.

Вот функция, которую я написал: `

 filterList (event) {
    var updatedList = this.props.array; 
    var filterText = this.state.text;
    updatedList = updatedList.filter(function(item){
      console.log(filterText);
      if(item.name === filterText){
        console.log('check', item.name);
      }
    });
  

Может ли кто-нибудь помочь мне в этом, вот ссылка на мой codepen: ССЫЛКА

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

1. Поскольку вы устанавливаете локальную переменную в отфильтрованный массив, вы не возвращаете ее, вы не обновляете состояние, вы фильтруете его, а затем выбрасываете.

Ответ №1:

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

Измените функцию handle, чтобы передать текст функции FilterList и вернуть результат

 handleChange(event) {
  var array = this.filterList(event.target.value);
  this.setState({ text: event.target.value, array: array });
},

filterList (filterText) {
  var updatedList = this.props.array;
  return updatedList.filter(function(item){
    return item.name === filterText;
  });
}
  

Обновите getInitialState для использования реквизитов:

 getInitialState() {
  return { text:'', array: this.props.array};
}
  

Затем используйте состояние вместо реквизита в вашем рендеринге:

 var arrayComponents = this.state.array.map(function(photo) {
     return <li className="photo photo-name">{photo.name} <img className="photo" src={photo.link}/></li>;
})
  

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

1. Спасибо, это работает, может быть, у вас есть решение для фильтрации отдельных букв? Теперь он фильтрует только тогда, когда целое имя совпадает с вводом

2. Конечно. Извините за поздний ответ. Вам просто нужно изменить сравнение equals. Если вы хотите, чтобы текст основывался на том, с чего он начинается. Таким Phot образом, соответствует, но oto не использует обычное повторное выражение. return new RegExp('^' filterText).test(item.name) . Если вы просто хотите сопоставить, содержится ли текст, можете сделать : return item.name.indexOf(filterText) !== -1 .

Ответ №2:

Во-первых, когда я запускаю ваш пример codepen, я не вижу никаких ошибок, указывающих на то, что this.state.text это не определено. Он ничего не фильтрует, но отображает значение this.state.text . Итак, проблема не совсем в том, что предполагает ваш вопрос…

Итак, как мы можем фильтровать эту вещь? По сути, идея компонентов ReactJS заключается в том, что все, что связано с текущим состоянием вашего компонента, должно быть this.state включено , и любые решения о том, что отображать на основе этого состояния, должны быть в render методе. И имейте в виду, что каждый раз, когда вы меняете состояние с помощью setState метода, это вызовет повторный рендеринг вашего компонента.

Имея это в виду, я бы настроил все следующим образом:

  1. ваш компонент получает список фотографий через array prop (я бы, наверное, назвал это как-то по-другому, поскольку он не очень описательный и очень близок к зарезервированному слову в Javascript)

  2. состояние компонента имеет одно значение: text (опять же, не очень описательное)

  3. компонент имеет handleChange обработчик для входного элемента. Я бы подключил это к onChange обработчику для элемента ввода — не волнуйтесь, он будет вызываться каждый раз, когда изменяется значение во входном элементе. Это должен быть единственный обработчик событий для элемента ввода, и все, что он должен сделать, это вызвать this.setState({ text: event.target.value });

  4. выполните фильтрацию списка в методе render. Ключевым моментом здесь является то, что вам не нужно сохранять отфильтрованный список ваших фотографий — все, что вы делаете с ним, это его рендеринг, поэтому делайте это только тогда, когда вам нужно (или, скорее, когда React считает, что вам нужно, и вызывает render метод). Итак, ваш метод визуализации будет выглядеть примерно так:

     render() {
        var myFilteredList = this.props.array.filter(function(item){
            console.log(filterText);
            if(item.name === filterText){
                console.log('check', item.name);
                return true;
            }
    
            return false;
        });
    
        var arrayComponents = myFilteredList.map(function(photo) {
            return <li className="photo photo-name">{photo.name} <img className="photo" src={photo.link}/></li>;
        });
    
        return (
        <div>
            <h1>Hello, {this.props.name}</h1>
            <p>{this.state.text}</p>
            <input type="text"  onKeyUp={this.handleChange} />
            <ul>
                {arrayComponents}
            </ul>
        </div>
        );
    }
      

Вот и все. Это имеет несколько преимуществ:

  1. это упрощает задачу — не поддерживайте какое-либо состояние для компонента вне this.state и, если оно вам нужно только для рендеринга, не поддерживайте его вообще.

  2. это делает ваш код более чистым — как я к этому подошел, у вашего компонента есть только два метода: handleChange и render

  3. он (должен быть) более производительным — React довольно хорошо решает, когда отображать на основе изменений состояния, и, как правило, лучше, когда компоненты имеют минимальное состояние. (Я говорю «должно быть» просто потому, что я его вообще не тестировал).