问题
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:
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?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!
回答1:
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
回答2:
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
来源:https://stackoverflow.com/questions/63259655/react-how-to-filter-data-array-using-multiple-checkbox