Adam Lau
Adam Lau

Reputation: 183

React/JavaScript, can someone explain why setState doesn't seem to correctly update the state during the function?

searchProject(title, language, length, experience) {
        if (title !== "") {
            const projects = this.state.projectList.filter(
                p => p.title === title 
            );
            this.setState({projectList : projects});
            }
        if (language !== "") {
            const projects = this.state.projectList.filter(
                p => p.language === language
            );
            this.setState({projectList : projects});
            }
        if (length !== 0) {
            const projects = this.state.projectList.filter(
                p => p.length === length 
            );
            this.setState({projectList : projects});
            }
        if (experience !== "") {
            const projects = this.state.projectList.filter(
                p => p.experience === experience
            );
            this.setState({projectList : projects});
            }
                        

        }

I have this snippet of code in my JS file which doesn't seem to do what I want it to do. It should be a filtering function which filters projects which have the same parameters as I specify. I'm very new to JS, so I don't think this is at all the most efficient way to do things, but I thought it should work. The logic of the function is that it sets the projectList state to the projectList which only contains the specified title, then it sets that new state to a state which only contains the specified language and so on... But it seems to only work for the last parameter I set. So if I fill in the experience parameter, it would ignore all projects which don't have that specified experience only. It doesn't matter what title or language or length I set. I think it has something to do with how setState works but I'm not sure. Could someone explain to me how I could fix this problem? Thank you!

Upvotes: 1

Views: 48

Answers (3)

Subhadeep
Subhadeep

Reputation: 149

One question: When do you call 'searchProject' method and with how many parameters at a single go?

From the given snippet it looks like this method can be called with multiple parameters at the same time which updates -'projectList' is every if block. So it would be better if you perform all conditional checks before you update the state a single go. Use a single 'projects' variable defined with let before all the conditional checks.

One small observation: Given snippet has arrow function syntax for filter methods, kindly update the 'searchProject' to the same syntax as well.

Upvotes: -1

Simon Lutterbie
Simon Lutterbie

Reputation: 167

I would load projectList once, filter it, then set state:

searchProject(title, language, length, experience) {
  let projects = this.state.projectList;

  if (title) { // Empty string is falsy, so this is the same as (title !== "")
    projects = projects.filter(...)
  }

  if (language) {
    projects  = projects.filter(...)
  }


  ...


  this.setState({projectList: projects});

}

Upvotes: 0

Shubham Khatri
Shubham Khatri

Reputation: 281626

From your code I am assuming that you call searchProject as an event handler. When you do that the state updates inside the function are batched.

Now since you have multiple if conditions within your code, you can have multiple blocks of state states that can happen together. and since all of them use this.state to filter, the last call to this.setState is what will be used by react after batching the results

The solution here is to call this.setState once like

searchProject(title, language, length, experience) {
  let projects = [...this.state.projectList];
  if (title !== "") {
      projects = projects.filter(
          p => p.title === title 
      );
  }
  if (language !== "") {
      projects = projects.filter(
          p => p.language === language
      );
  }
  if (length !== 0) {
      projects = projects.filter(
          p => p.length === length 
      );
  }
  if (experience !== "") {
      projects = projects.filter(
          p => p.experience === experience
      );
  }
  this.setState({ projectList: projects});

}

Upvotes: 3

Related Questions