0
movies = [
   {
    id:1,
    title: "movie1",
    genre:["action","sci-fi"],
    country:["usa","uk"]
   },
   {
    id:2,
    title: "movie2",
    genre:["action","comedy"],
    country:["usa","ireland"]
   },
   {
    id:3,
    title: "movie3",
    genre:["comedy","romance"],
    country:["ireland","uk]
   },
]

I want to filter movies by genre and country. I can do that in a very weird method. But I wonder what's the shortcut of filtering. Is there any option that I can filter if the prop or props exist, if not leave the original?

const Component = ({ genre, country }) => {
  const [movies,setMovies]=useState([]);
  const [filteredMovies,setFilteredMovies]=useState([])

    useEffect(()=>{
    //fetch from api and set movies
  },[])
  
  useEffect(()=>{
    setFilteredMovies(
      movies.filter((item) =>
        {
           if(genre || country){
              if(!country){
                 return item.genre.includes(genre)
              }elseif(!genre){
                 return item.country.includes(country)
              }else{
                 return item.genre.includes(genre) && item.country.includes(country)
              }
           }else return item
        }
      )
    );
  },[movies,genre,country])

  return (
    <div>
      {filteredMovies.map((item) => (
        <Movie item={item} key={item.id} />
      ))}
    </div>
  );
}

3 Answers 3

1

I recommend using lodash, its make filter simple

   _.filter(movies , { genre: ["action"] });

you can check the documentation: https://lodash.com/docs/4.17.15#filter

and please try my experiment:

Edit lodash

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

Comments

0

Rearrange your data in a way that allows you to enter a single value or object which can be used to filter the data in the movies. For example if you'd arrange your filter like this: (which you kind of already if you wouldn't destructure)

const filters = {
  genre: 'action',
  country: 'ireland'
};

Then you could loop over each movie and use the properties of the filters to access only the properties of a movie that you would like to check, like the pseudo-code below.

movie[property].includes(value)

When doing this you can leave out, or add any filter that you'd like.

Do be aware that in the current state the snippet below assumes that it only has to work with an array.

const filters = {
  genre: 'action',
  country: 'ireland'
};
  
const movies = [
  {
    id: 1,
    title: "movie1",
    genre: ["action", "sci-fi"],
    country: ["usa", "uk"]
  },
  {
    id: 2,
    title: "movie2",
    genre: ["action", "comedy"],
    country: ["usa", "ireland"]
  },
  {
    id: 3,
    title: "movie3",
    genre: ["comedy", "romance"],
    country: ["ireland", "uk"],
  },
];

const filterMovies = (movies, filters) =>
  movies.filter(movie => 
    Object.entries(filters).every(([key, value]) => 
      movie[key].includes(value)
    )
  )

const result = filterMovies(movies, filters);
console.log(result);

1 Comment

It's a good idea to make all filters in an object. Thank you.
0

To make this a little more ES6-y

movies.filter((item) =>{

    const [movieGenre, movieCountry] = [item.genre.includes(genre),item.country.includes(country)]

  if(movieGenre && movieCountry) true
  if(!movieGenre && !movieCountr) false

 return movieGenre ? movieGenre : movieCountry

      })

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.