Skip to content
  • Unlock Pro
  • Log in with GitHub
Solution
Submitted 12 months ago

Job listings with filtering using React

react
P
Miran Legin•740
@miranlegin
A solution to the Job listings with filtering challenge
View live sitePreview (opens in new tab)View codeCode (opens in new tab)

Solution retrospective


What are you most proud of, and what would you do differently next time?

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.

Code
Select a file

Please log in to post a comment

Log in with GitHub

Community feedback

  • Luka•820
    @LukaKobaidze
    Posted 12 months ago

    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! 🤗

    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
Frontend Mentor logo

Stay up to datewith new challenges, featured solutions, selected articles, and our latest news

Frontend Mentor

  • Unlock Pro
  • Contact us
  • FAQs
  • Become a partner

Explore

  • Learning paths
  • Challenges
  • Solutions
  • Articles

Community

  • Discord
  • Guidelines

For companies

  • Hire developers
  • Train developers
© Frontend Mentor 2019 - 2025
  • Terms
  • Cookie Policy
  • Privacy Policy
  • License

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub

How does the accessibility report work?

When a solution is submitted, we use axe-core to run an automated audit of your code.

This picks out common accessibility issues like not using semantic HTML and not having proper heading hierarchies, among others.

This automated audit is fairly surface level, so we encourage to you review the project and code in more detail with accessibility best practices in mind.

How does the CSS report work?

When a solution is submitted, we use stylelint to run an automated check on the CSS code.

We've added some of our own linting rules based on recommended best practices. These rules are prefixed with frontend-mentor/ which you'll see at the top of each issue in the report.

The report will audit 1st-party linked stylesheets, and styles within <style> tags.

How does the HTML validation report work?

When a solution is submitted, we use html-validate to run an automated check on the HTML code.

The report picks out common HTML issues such as not using headings within section elements and incorrect nesting of elements, among others.

Note that the report can pick up “invalid” attributes, which some frameworks automatically add to the HTML. These attributes are crucial for how the frameworks function, although they’re technically not valid HTML. As such, some projects can show up with many HTML validation errors, which are benign and are a necessary part of the framework.

Oops! 😬

You need to be logged in before you can do that.

Log in with GitHub