javascriptreactjsdata-bindingbind

React: issue with the search and filter function


I'm working on a component that should be able to:

  1. Search by input - Using the input field a function will be called after the onBlur event got triggered. After the onBlur event the startSearch() method will run.

  2. Filter by a selected genre - From an other component the user can select a genre from a list with genres. After the onClick event the startFilter() method will run.

GOOD NEWS: I got the 2 functions above working.

BAD NEWS: The above 2 functions don't work correct. Please see the code underneath. The 2 calls underneath work, but only if I comment one of the 2 out. I tried to tweak the startSearch() method in various ways, but I just keep walking to a big fat wall.

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

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

QUESTION How can I get the filter/search method working?. Unfortunately simply putting them in an if/else is not the solution (see comments in the code).

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>
    );
  }
}


Solution

  • The question you are asking is not clear. But try to be explicit with your component to help debug the issue. For example, use a constructor and declare your component state in there. Also do your .bind for the event in there to be concise.

    The following example captures the state variable to be true when the onBlur event is fired, which is the same as its initial state value:

    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} 
            />
        )
    }