Reputation: 183
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
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
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
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