简体   繁体   中英

Filter an Array based off user input string and menu dropdown items

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:

  1. type in a search query and filter the array
  2. use the menu to select multiple pattern options to filter array
  3. filter the exercise array with both search and menu selection.

 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?

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

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) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM