Job listings with filtering using React

Solution retrospective
If i would start this project again i would invest some extra time beforehand to find out what are the solutions to filter/search something with multiple search queries/filters.
What challenges did you encounter, and how did you overcome them?I had some problems stacking multiple tags on top of each other and showing items that has multiple selected tags.
What specific areas of your project would you like help with?Although this demo works i'm not so sure if this is the most elegant way to handle filtering with multiple options. I would love to hear other opinions how to achieve this functionality in a different way especially how to write logic when multiple options are selected.
Please log in to post a comment
Log in with GitHubCommunity feedback
- @LukaKobaidze
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, includingrole
,level
,languages
, andtools
. This state also removes the need for havingfilterCounter
state and two functionsincrementCounterHandler()
,decrementCounterHandler()
, because now we can get the "count" by usingfilter.length
.Now In the same component, I would remove
filterJobs()
function andfilteredJobs
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 auseEffect
hook with dependency array that includesfilter
. Now, whenever we updatefilter
,useEffect
runs the code that's inside of it and updates thefilteredJobs
state.Next up, I would replace
addTagHandler()
andremoveTagHandler()
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 theFilterPanel.js
component, I only passfilter
state as a prop.And to the
Card.js
component instead of passingrole
,level
,languages
,tools
props, I only pass one prop to ittags={[card.role, card.level, ...card.languages, ...card.tools]}
.And finally, I would update the way we render filter tags and map over the
filter
andtags
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! 🤗
Marked as helpful
Join our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord