Reputation: 93
I am struggling to filter an array in one of my react projects.
My React App has a search bar that returns a searchQuery as a string and menu of movement patterns that when clicked gets added to the pattern array. The user should be able to:
const searchQuery = "ben";
const pattern = [];
const exercises = [
{
name: "bench press",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["squat", "hinge"]
},
{
name: "pushup",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "pullup",
movement: ["pull", "squat", "hinge"]
},
{
name: "bent over row",
movement: ["push", "pull", "hinge"]
}
];
let filteredExercises = [];
if (searchQuery && pattern) {
filteredExercises = exercises.filter(
exercise =>
exercise.name.toLowerCase().indexOf(searchQuery) !== -1 &&
exercise.movement.some(movement =>
pattern.some(pattern => pattern == movement)
)
);
} else if (pattern.length > 0) {
filteredExercises = exercises.filter(exercise =>
exercise.movement.some(movement =>
pattern.some(pattern => pattern == movement)
)
);
} else if (searchQuery) {
filteredExercises = exercises.filter(
exercise => exercise.name.toLowerCase().indexOf(searchQuery) !== -1
);
console.log(filteredExercises);
}
console.log(filteredExercises);
The first two conditional statements work and return the correct data. As soon as I add the third conditional statement to filter by searchQuery I get an empty array in return.
Can anyone help with this?
Upvotes: 0
Views: 48
Reputation: 91
I think checking the array as a truthy value instead of the length of the array was your biggest issue.
However, I also think this could be written more simply by moving the repeated code to functions and just running one filter
. If you don't like ternary operators you can replace what I have with your if
/if else
clauses (don't forget the returns though).
const searchQuery = "ben";
const pattern = [];
const exercises = [
{
name: "bench press",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["squat", "hinge"]
},
{
name: "pushup",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "pullup",
movement: ["pull", "squat", "hinge"]
},
{
name: "bent over row",
movement: ["push", "pull", "hinge"]
}
];
const excerciseTest = (name, searchQuery) => {
return name.toLowerCase().includes(searchQuery.toLowerCase())
}
const patternTest = (movement, pattern) => {
return movement.some(movement => {
return pattern.some(pattern => pattern === movement)
})
}
const filteredExercises = exercises.filter(excercise => {
// if (searchQuery && pattern.length > 0)
return (searchQuery && pattern.length > 0)
? excerciseTest(excercise.name, searchQuery) && patternTest(excercise.movement, pattern)
// else if (pattern.length > 0)
: pattern.length > 0
? patternTest(excercise.movement, pattern)
// else if (searchQuery)
: searchQuery
? excerciseTest(excercise.name, searchQuery)
: false
})
console.log(filteredExercises)
Upvotes: 0
Reputation: 92461
An empty array is truthy which means your first if
is firing when pattern
is empty — it never makes it to your last else if
. You can test for pattern.length
instead and it should work
const searchQuery = "ben";
const pattern = [];
const exercises = [
{
name: "bench press",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "squat",
movement: ["squat", "hinge"]
},
{
name: "pushup",
movement: ["push", "pull", "squat", "hinge"]
},
{
name: "pullup",
movement: ["pull", "squat", "hinge"]
},
{
name: "bent over row",
movement: ["push", "pull", "hinge"]
}
];
let filteredExercises = [];
if (searchQuery && pattern.length) {
filteredExercises = exercises.filter(
exercise =>
exercise.name.toLowerCase().indexOf(searchQuery) !== -1 &&
exercise.movement.some(movement =>
pattern.some(pattern => pattern == movement)
)
);
} else if (pattern.length > 0) {
filteredExercises = exercises.filter(exercise =>
exercise.movement.some(movement =>
pattern.some(pattern => pattern == movement)
)
);
} else if (searchQuery) {
filteredExercises = exercises.filter(
exercise => exercise.name.toLowerCase().indexOf(searchQuery) !== -1
);
console.log(filteredExercises);
}
console.log(filteredExercises);
Upvotes: 2