nikola96gospodinov
nikola96gospodinov

Reputation: 49

React: Display filtered array items based on click event

Basically what I have is an array of projects (objects) with their names and technologies used (that's another array). What I am trying to do is to filter the projects based on which button it's clicked. For example if a user clicks the 'React' button it should only display the projects that have 'React' in their array of technologies. If a user clicks the 'All' button it should display all the projects. Here is the code that I have:

const projects = [
    {
        name: 'Poject 1',
        technologies: ['React', 'Gatsby']
    },
    {
        name: 'Project 2',
        technologies: ['HTML', 'Node.js']
    },
    {
        name: 'Project 3',
        technologies: ['React', 'Node.js']
    },
    {
        name: 'Project 4',
        technologies: ['HTML', 'CSS']
    }
    ]
    
    const displayProjects = () => {
       const [tech, setTech] = useState('')
    
       const filteredProjects = projects.filter((project) => {
            return project.technologies.some(t => t === tech)
        })
    
       return (
          <button>All</button>
          <button onClick={() => setTech(tech === 'React')}>React</button>
          <button onClick={() => setTech(tech === 'HTML')}>HTML</button>
    
          {filteredProjects.map(function (filteredProject) {
             return (
                <div>
                   {filteredProject.name}
                </div>
             )
          })}
       )
    }

I realize that I missing something in my code but I feel like I am close to getting to the solution. Any suggestions are hugely appreciated.

Upvotes: 0

Views: 374

Answers (2)

Ketan Ramteke
Ketan Ramteke

Reputation: 10655

App output:

enter image description here

You have to set state like this:

<button onClick={() => setTech('React')}>React</button>
<button onClick={() => setTech('HTML')}>HTML</button>

full working app code:

import React, { useState, useEffect } from "react";
import Axios from "axios";
import "./style.css";

import React from "react";
const projects = [
  {
    name: "Poject 1",
    technologies: ["React", "Gatsby"]
  },
  {
    name: "Project 2",
    technologies: ["HTML", "Node.js"]
  },
  {
    name: "Project 3",
    technologies: ["React", "Node.js"]
  },
  {
    name: "Project 4",
    technologies: ["HTML", "CSS"]
  }
];

const App = () => {
  const [tech, setTech] = useState("");

  const filteredProjects =
    tech === ""
      ? projects
      : projects.filter(project => project.technologies.includes(tech));

  return (
    <>
      <button onClick={() => setTech("")}>All</button>
      <button onClick={() => setTech("React")}>React</button>
      <button onClick={() => setTech("HTML")}>HTML</button>

      {filteredProjects.map(function(filteredProject) {
        return <div>{filteredProject.name}</div>;
      })}
    </>
  );
};

export default App;

live working app: stackblitz

Upvotes: 2

Nick
Nick

Reputation: 16576

I actually think the only issue you have is your state setting functions are being called incorrectly. It should be this:

<button onClick={() => setTech('React')}>React</button>
<button onClick={() => setTech('HTML')}>HTML</button>

As you currently have it, you're setting tech to either true or false (the result of the identity comparison operations)!

Upvotes: 1

Related Questions