Search code examples
javascriptreactjsfilteronchangesetstate

Not understanding what's wrong with my Filter function and state in React


I have the following code:

Parent component:

class App extends Component {
  state = {
    colors: []
  };

  async componentDidMount() {
    const fetched = await fetch("./response.json");
    const fetchedJson = await fetched.json();
    const res = fetchedJson.colors;

    this.setState({
      colors: res
    });
  }

 
  filterItems = (name) => {
    const lowerCaseName = name.toLowerCase();
    const newColors = [...this.state.colors];
    const res = newColors.filter((color) => {
      const lowerCaseColorName = color.name.toLowerCase();
      return lowerCaseColorName.includes(lowerCaseName);
    });

    this.setState({
      colors: res
    });
  };

  render() {
    const { colors } = this.state;
    return (
      <div>
        <InputText filterItems={this.filterItems} />
        <AllData colors={colors} />
      </div>
    );
  }
}

And this is my Child component:

class Filter extends Component {
  state = {
    inputVal: ""
  };

  onChange = (e) => {
    this.setState({
      inputVal: e.target.value
    });
    this.props.filterItems(e.target.value);
  };

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <input
          type="text"
          onChange={this.onChange}
          value={this.state.inputVal}
        />
      </form>
    );
  }
}

export default Filter;

There's also another child component called AllData but its job is just displaying out data and put styling on it, so I'm not including it here.

Currently the data displayed are just:

Fire Dragon
Water Horse
Earth Bird
Wood Dog
Wind Cat

Here are my questions:

  1. The filter function works fine when I type in a word into the search box in filter. However, when I backtrack and remove a previous character down to the whole input string, the res array doesn't return its whole original arrays but instead retains the result of the filter only when I type more.

Ex: When I type in the string "cat", res becomes: [{name: "Wind Cat", id: 5} However I remove that string by backtracking on the keyboard, res is still at [{name: "Wind Cat", id: 5}. Why is it not going back to returning all of the items, and how do I fix this?

  1. I currently have this code:
onChange = (e) => {
    this.setState({
      inputVal: e.target.value
    });
    this.props.filterItems(e.target.value);
  };

However, if I change it to:

this.props.filterItems(this.state.inputVal);

and console.log(name) out in the parent component at filterItems, every time I type in a string, it seems like the console.logged name only display the character before.

Ex: If I type in the string c -> name would be "" (empty) If I type in the string ca -> name would be c Why is this happening?


Solution

  • class App extends Component {
        state = {
          colors: [],
          filtered: [],
        };
      
        async componentDidMount() {
          const fetched = await fetch("./response.json");
          const fetchedJson = await fetched.json();
          const res = fetchedJson.colors;
      
          this.setState({
            colors: res
          });
        }
      
       
        filterItems = (name) => {
          const lowerCaseName = name.toLowerCase();
          const newColors = [...this.state.colors];
    
          const filtered = newColors.filter(color => {
            const parts = color.split(' ').map(part => part.toLowerCase());
            return parts.reduce((carry, part) => {
              return carry ? carry : part.startsWith(lowerCaseName);
            }, false);
          });
    
          this.setState({
            filtered,
          });
        };
      
        render() {
          const { colors, filtered } = this.state;
          return (
            <div>
              <InputText filterItems={this.filterItems} />
              <AllData colors={filtered ? filtered : colors} />
            </div>
          );
        }
    }