反应:搜索和过滤器功能出现问题

时间:2019-05-23 19:51:30

标签: javascript reactjs data-binding bind

我正在研究一个应该能够做到的组件

  1. 按输入搜索-触发onBlur事件后,将使用输入字段调用一个函数。 onBlur 事件发生后, startSearch ()方法将运行。

  2. 按选定流派过滤-用户可以从其他组件中从具有流派的列表中选择流派。在 onClick 事件之后,将运行 startFilter ()方法。

好消息: 我已经完成了上面的两个功能。

坏消息: 上述2个功能无法正常使用。请参见下面的代码。在工作下面有2个调用,但是仅当我注释掉2个之一时。我试图以各种方式调整 startSearch ()方法,但我一直走到一堵胖墙。

//////Searching works
//////this.filter(this.state.searchInput);

//Filtering works           
this.startFilter(this.state.searchInput);

问题 如何使过滤器/搜索方法起作用?。不幸的是,简单地将它们放在if / else中不是解决方案(请参阅代码中的注释)。

import { Component } from 'preact';
import listData from '../../assets/data.json';
import { Link } from 'preact-router/match';
import style from './style';

export default class List extends Component {
  state = {
    selectedStreamUrl: '',
    searchInput: '',
    showDeleteButton: false,
    searchByGenre: false,
    list: []
  };

  startFilter(input, filterByGenre) {
    this.setState({
      searchByGenre: true,
      searchInput: input,
      showDeleteButton: true
    });
    alert('startFilter  ');
    console.log(this.state.searchByGenre);
    /////////---------------------------------
    document.getElementById('searchField').disabled = false;
    document.getElementById('searchField').value = input;
    document.getElementById('searchField').focus();
    // document.getElementById('searchField').blur()
    document.getElementById('searchField').disabled = true;

    console.log(input);
    this.filter(input);
  }

  //search
  startSearch(input) {
    alert('startSearch  ');
    console.log(this.state.searchByGenre);

    //komt uit render()
    if (!this.state.searchByGenre) {
      //check for input

      this.setState({
        searchInput: input.target.value,
        showDeleteButton: true
      });

      //Searching works
      //this.filter(this.state.searchInput);

      //Filtering works
      this.startFilter(this.state.searchInput);

      // DOESNT WORK:
      // if (this.state.searchInput != "") {
      // 	this.filter(this.state.searchInput);
      // } else {
      // 	this.startFilter(this.state.searchInput);
      // }
    }
  }

  setAllLists(allLists) {
    console.log('setAllLists');
    console.log(this.state.searchByGenre);
    this.setState({ list: allLists });
    //document.body.style.backgroundColor = "red";
  }

  filter(input) {
    let corresondingGenre = [];
    let filteredLists = listData.filter(item1 => {
      var test;
      if (this.state.searchByGenre) {
        alert('--this.state.searchByGenre');
        //filterByGenre
        //& item1.properties.genre == input

        for (var i = 0; i < item1.properties.genre.length; i++) {
          if (item1.properties.genre[i].includes(input)) {
            corresondingGenre.push(item1);
            test = item1.properties.genre[i].indexOf(input) !== -1;

            return test;
          }
          this.setState({ list: corresondingGenre });
        }
      } else {
        //searchByTitle
        alert('--default');
        test = item1.title.indexOf(input.charAt(0).toUpperCase()) !== -1;
      }
      return test;
    });
    console.log('filterdLists:');
    console.log(filteredLists);
    console.log('corresondingGenre:');
    console.log(corresondingGenre);
    //alert(JSON.stringify(filteredLists))
    this.setState({ list: filteredLists });
  }

  removeInput() {
    console.log('removeInput    ');
    console.log(this.state.searchByGenre);
    this.setState({
      searchInput: '',
      showDeleteButton: false,
      searchByGenre: false
    });
    document.getElementById('searchField').disabled = false;
    this.filter(this.state.searchInput);
  }

  render() {
    //alle 's komen in deze array, zodat ze gefilterd kunnen worden OBV title.
    if (
      this.state.list === undefined ||
      (this.state.list.length == 0 && this.state.searchInput == '')
    ) {
      //init list
      console.log('render ');
      console.log(this.state.searchByGenre);
      this.filter(this.state.searchInput);
    }

    return (
      <div class={style.list_container}>
        <input
          class={style.searchBar}
          type="text"
          id="searchField"
          placeholder={this.state.searchInput}
          onBlur={this.startSearch.bind(this)}
        />

        {this.state.searchByGenre ? <h1>ja</h1> : <h1>nee</h1>}
        {this.state.showDeleteButton ? (
          <button class={style.deleteButton} onClick={() => this.removeInput()}>
            Remove
          </button>
        ) : null}
        {this.state.list.map((item, index) => {
          return (
            <div>
              <p>{item.title}</p>
            </div>
          );
        })}
      </div>
    );
  }
}

3 个答案:

答案 0 :(得分:2)

您要问的问题不清楚。但是,请尝试对组件进行明确说明以帮助调试问题。例如,使用构造函数并在其中声明组件状态。另外,为简洁起见,请为您的.bind做事件。

以下示例在触发onBlur事件时将状态变量捕获为true,这与其初始状态值相同:

class List extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        searchByGenre: true
    };

    this.startSearch = this.startSearch.bind(this);
}

startSearch() {
    // This value is true
    console.log(this.state.searchByGenre)
}

render() {
    return (
        <input 
            type="text" 
            id="searchField" 
            placeholder="Search" 
            value={this.state.searchInput} 
            onBlur={this.startSearch} 
        />
    )
}

答案 1 :(得分:1)

要使搜索和过滤器正常工作,您需要两个数组。

macro_rules! match_token_pattern {
    ($parser:ident, $a:ident) => {{
        let a = $parser.$a();

        if a != None {
            Some(a)
        } else {
            None
        }
    }};

    ($parser:ident, $a:ident, $b:ident) => {{
        let a = $parser.$a();
        let b = $parser.$b();

        if a != None && b != None {
            Some((a, b))
        } else {
            None
        }
    }};

    ($parser:ident, $a:ident, $b:ident, $c:ident) => {{
        let a = $parser.$a();
        let b = $parser.$b();
        let c = $parser.$c();

        if a != None && b != None && c != None {
            Some((a, b, c))
        } else {
            None
        }
    }};
}

您的搜索功能将使用state = { selectedStreamUrl: "", searchInput: "", showDeleteButton: false, // searchByGenre: false, // removed, will use filter by from a list // by default both arrays have the same value list: listData, // holds the original data, doesn't change filteredList: listData, // holds filterd list, filtered when the user types in input // by default filter by title, will change when user, use a value from a list filterBy: 'title', } 值来过滤数组。无需创建多个功能。这样可以为您提供灵活性,因为您可以使用下拉菜单中的多个值进行过滤,而无需更改代码。

this.state.filterBy

删除输入功能

startSearch = (value) => {

  const search = value.toLowerCase();
  // get filter value title, genre, etc
  const searchKey = this.state.filterBy;

  this.setState({
    searchInput: value,
    filteredList: this.state.list.filter(item => {
      // filter base on key item['title'] or item['genre'] etc
      return item && item[searchKey].toLowerCase().includes(search)
    }),
    showDeleteButton: !!value,
  })

}

我看到您正在做很多removeInput = () => { this.setState({ filterBy: 'title', showDeleteButton: false, searchInput: '', }, () => this.startSearch(this.state.searchInput)); } 。不要直接操纵dom,让react为您管理。

在下方查看演示

document.getElementById("searchField").disabled = false;
h1, p {
  font-family: Lato;
}

.container {
  display: flex;
  flex-direction: row;
  border-bottom-style: solid;
  margin-bottom: 5px;
}

.image-container {
  flex-grow: 0;
}

.info-container {
  flex-grow: 1;
  margin-left: 10px
}

.title {
  margin-top: 0;
}

.cover {
  width: 60px;
}

答案 2 :(得分:0)

两种方法:

将绑定更改为构造函数(以及状态!)

constructor(props) {
        super(props);

        this.state = { searchByGenre: true }

        this.startSeach = startSearch.bind(this);
    }

    startSearch(searchByGenre) {
        //This is false after the call 
        console.log(this.state.searchByGenre)
    }

    render() {
        return (
            <input class={style.searchBar} type="text" id="searchField" placeholder="Search" value={this.state.searchInput} onBlur={this.startSearch} >
            </input>
        )
    }

这样,您可以将startSearch与参数一起使用:

<input class={style.searchBar} 
  type="text" 
  id="searchField" 
  placeholder="Search" 
  value={this.state.searchInput} 
  onBlur={() => this.startSearch(this.state.searchByGenre)} 
>

OR ,您可以将startSearch更改为箭头函数,并从构造函数中删除绑定:

startSearch = (searchByGenre) => {
  //This is false after the call 
  console.log(this.state.searchByGenre)
}

您可以查看为什么发生这种情况here

编辑:该链接只讨论typeScript,但忽略它,而将重点放在 arrow function / bind 部分