Helloπ Your solution on filtering jobs is nice, great job! There are a few things I would do differently, so I'm going to answer your last question and give you an example of how I would handle filtering by changing things up in your code.
In your FilterableCards.js
component I would remove all 5 useState hooks below...
function FilterableCards({ cards }) {
const [role, setRole] = useState(null);
const [level, setLevel] = useState(null);
const [languages, setLanguages] = useState([]);
const [tools, setTools] = useState([]);
const [filterCounter, setFilterCounter] = useState(0);
...
And replace it with only one state, like this:
function FilterableCards({ cards }) {
const [filter, setFilter] = useState([]);
...
This filter
state is an array of strings that will contain any filtering option, including role
, level
, languages
, and tools
. This state also removes the need for having filterCounter
state and two functions incrementCounterHandler()
, decrementCounterHandler()
, because now we can get the "count" by using filter.length
.
Now In the same component, I would remove filterJobs()
function and filteredJobs
variable and add the following:
function FilterableCards({ cards }) {
const [filter, setFilter] = useState([]);
const [filteredJobs, setFilteredJobs] = useState(cards);
useEffect(() => {
if (filter.length > 0) {
setFilteredJobs(
cards.filter((card) => {
const cardTags = [card.role, card.level, ...card.languages, ...card.tools];
return filter.every((filterOption) => {
return cardTags.includes(filterOption);
});
})
);
} else {
setFilteredJobs(cards);
}
}, [filter, cards]);
...
As you can see, I added one more state filteredJobs
and a useEffect
hook with dependency array that includes filter
. Now, whenever we update filter
, useEffect
runs the code that's inside of it and updates the filteredJobs
state.
Next up, I would replace addTagHandler()
and removeTagHandler()
functions with the following:
...
function addTagHandler(tag) {
setFilter((state) => {
return [...state, tag];
});
}
function removeTagHandler(tag) {
setFilter((state) => {
return state.filter((filteringTag) => filteringTag !== tag);
});
}
...
It works just like the functions in your solution, but now I only update filter
state, because we save every type of tag in it.
Now, instead of passing role
, level
, languages
, tools
props to the FilterPanel.js
component, I only pass filter
state as a prop.
And to the Card.js
component instead of passing role
, level
, languages
, tools
props, I only pass one prop to it tags={[card.role, card.level, ...card.languages, ...card.tools]}
.
And finally, I would update the way we render filter tags and map over the filter
and tags
props.
I forked your repo and updated it just like I explained in this answer, so you can see every file I changed. You can click my latest commit to compare your solution with mine, link here!
If something's not clear in my solution for filtering, feel free to point it out.
Happy Coding! π€