1

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!

2
  • So whenever you call setState the entire component re-renders and I'm assuming that this code will be called again. That's why the projectList only updates the last parameter. In order to do all of it, I suggest making project a let project and filter upon the filters.Let me know if you want me to elaborate more @Adam Lau. Commented Jun 3, 2020 at 5:30
  • Hi @gnahum, thanks for the reply! Could you elaborate a bit more on the let project bit? Thanks. Commented Jun 3, 2020 at 5:32

3 Answers 3

3

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

}
Sign up to request clarification or add additional context in comments.

Comments

0

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

}

Comments

-1

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.

1 Comment

Please ask for clarification in the comments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.