0

I intend to filter data by selecting different checkbox through the following codes:

const movieData = [
  {
    title: "movie 0",
    genre: ""
  },
  {
    title: "movie 1",
    genre: ["action", "thriller"]
  },
  {
    title: "movie 2",
    genre: ["comedy", "drama"]
  },
  {
    title: "movie 3",
    genre: ["comedy", "action"]
  },
  { title: "movie 4", genre: "thriller" },
  {
    title: "movie 5",
    genre: "comedy"
  },
  {
    title: "movie 6",
    genre: "action"
  },
  {
    title: "movie 7",
    genre: "drama"
  }
];

const movie = [
  { genre: "thriller" },
  { genre: "comedy" },
  { genre: "action" },
  { genre: "drama" }
];

const FilterMethod01 = () => {
  const [genre, setGenre] = useState([""]);
  const [filteredGenre, setFilteredGenre] = useState([""]);

  const handleChange = e => {
    if (e.target.checked) {
      setGenre([...genre, e.target.value]);
    } else {
      setGenre(genre.filter(id => id !== e.target.value));
    }
  };

  useEffect(() => {
    setFilteredGenre(
      movieData.filter(movie =>
        genre.some(category => category === movie.genre)
      )
    );
  }, [genre]);

  return (
    <Fragment>
      <FormControl>
        <FormGroup>
          {movie.map(movie => (
            <FormControlLabel
              control={<Checkbox onChange={handleChange} />}
              label={movie.genre}
              value={movie.genre}
            />
          ))}
        </FormGroup>
      </FormControl>

      {filteredGenre
        .map((movie, index) => (
          <Card style={{ background: "lightgreen", marginBottom: "5px" }}>
            <Typography gutterBottom variant="h6" noWrap>
              title: {movie.title}
            </Typography>
            <Typography gutterBottom variant="h6" noWrap>
              genre: {movie.genre}
            </Typography>
          </Card>
        ))}
    </Fragment>
  );
};

However, I have the following problems with this code:

  1. All the mapped data ["movie 0", "movie 1", "movie 2", "movie 3"...] doesn't appear by default. How can I get all the mapped data to appear by default?

  2. The mapped data only filters a single string (e.g. {genre: ""} ) instead of an array of strings (e.g. {genre: ["thriller", "action"]}). How can I select the "action" checkbox to trigger "movie 1", "movie 3", & "movie 6" to appear?


    #Checkout my codesandbox here.#


    If there are other better practices to achieve this result, please let me know as well. Thank you so much guys!

2 Answers 2

0

There are some fixes:

  • remove ambiguous blank string:
const [genre, setGenre] = useState([]);
const [filteredGenre, setFilteredGenre] = useState([]);
  • if not filter any thing, just return all the movie data
  • if filter, return any movie data which include genre of the filtered. Tricky part here is that movie data genre has multiple type, array and string, so a simple way to handle this is to wrap it in an array then flat
useEffect(() => {
  if (genre.length === 0) {
    setFilteredGenre(movieData)
  } else {
    setFilteredGenre(
      movieData.filter(movie =>
        genre.some(category => [movie.genre].flat().includes(category))
      )
    )
  }
}, [genre])

Below is the forked codesandbox

Edit flamboyant-lake-brw26

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

Comments

0

Here's some suggestions, you should keep consistent on declaring arrays of object, and the array inside.

const movieData = [
  {
    title: "movie 0",
    genre: []
  },
  {
    title: "movie 1",
    genre: ["action", "thriller"]
  },
  {
    title: "movie 2",
    genre: ["comedy", "drama"]
  },
  {
    title: "movie 3",
    genre: ["comedy", "action"]
  },
  { title: "movie 4", 
    genre: ["romance"] 
  },
  {
    title: "movie 5",
    genre: ["horror", "drama"]
  },
  {
    title: "movie 6",
    genre: ["comedy"]
  },
  {
    title: "movie 7",
    genre: []
  }
];

Maybe it could solve the logic to loop inside the array.

*CMIIW because I'm new :D

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.