0

I have JSON local Data that I display into the dom, then I've created a new array (tags) where I stored some of the elements from the original Data(datas) to use them to filter the state(Datas) Onclick event, I've used the filter function but when I debugged the function it returned an array of the element itself.

What do you think guys?

PS : I'm a beginner with React

<--App Comp-->

import "./App.scss";
import datas from "./data.json";
import CardList from "./components/CardList/CardList";
import Header from "./components/Header/Header";


const App = () => {
  return (
    <div className="App">
      <Header />
      <CardList datas={datas} />
    </div>
  );
};

export default App;

<--CardList Comp-->

import Card from "../Card/Card";
import "./CardList.scss";
import React,{useState} from "react";

const CardList = (props) => {

  return (
    <ul className="CardList">
      {props.datas.map((data) => {
        const tags = [data.role, data.level, ...data.languages, ...data.tools];
        
        return (
          <Card
            key={data.id}
            company={data.company}
            logo={data.logo}
            new={data.new}
            featured={data.featured}
            position={data.position}
            postedAt={data.postedAt}
            contract={data.contract}
            tags={tags}
            filterTag= {filterTag}
          />
        );
      })}
    </ul>
  );
};

export default CardList;

<--Card Comp-->

import "./Card.scss";
import React,{useState} from "react";


const Card = (props) => {
  const [jobs, setJobs] = useState(props.datas);

  const filterTag  = (tag) => {
    const newJob = jobs.filter((job)=> job.tag === tag);
    console.log(newJob);
    setJobs(newJob);
  }

  return (
    
    <li key={props.id} className="Card">
      <div className="image">
        <img src={props.logo} alt={`${props.company} logo`} />
      </div>
      <div className="content">
        <span className="company">{props.company}</span>
        {props.new && <span className="new">New!</span>}
        {props.featured && <span className="featured">Featured</span>}
        <h2>{props.position}</h2>
        <ul>
          <li>{props.postedAt}</li>
          <li>{props.contract}</li>
          <li>{props.location}</li>
        </ul>
      </div>
      <ul className="tags">
        {props.tags.map((tag, index) => {
          return <li key={index} onClick={()=> filterTag(tag)}>{tag}</li>;
        })}
      </ul>
    </li>
  );
};

export default Card;

<--Data-->

[
  {
    "id": 1,
    "company": "Photosnap",
    "logo": "./images/photosnap.svg",
    "new": true,
    "featured": true,
    "position": "Senior Frontend Developer",
    "role": "Frontend",
    "level": "Senior",
    "postedAt": "1d ago",
    "contract": "Full Time",
    "location": "USA Only",
    "languages": ["HTML", "CSS", "JavaScript"],
    "tools": []
  },
  {
    "id": 2,
    "company": "Manage",
    "logo": "./images/manage.svg",
    "new": true,
    "featured": true,
    "position": "Fullstack Developer",
    "role": "Fullstack",
    "level": "Midweight",
    "postedAt": "1d ago",
    "contract": "Part Time",
    "location": "Remote",
    "languages": ["Python"],
    "tools": ["React"]
  },
  {
    "id": 3,
    "company": "Account",
    "logo": "./images/account.svg",
    "new": true,
    "featured": false,
    "position": "Junior Frontend Developer",
    "role": "Frontend",
    "level": "Junior",
    "postedAt": "2d ago",
    "contract": "Part Time",
    "location": "USA Only",
    "languages": ["JavaScript"],
    "tools": ["React", "Sass"]
  }
]
0

2 Answers 2

1

I have changed the previous answer because of your comment

here is the link:

https://codesandbox.io/s/youthful-kilby-vvlps

Let's explain a little more

first of all I changed this

const tags = [data.role, data.level, ...data.languages, ...data.tools];

to

const tags = [
            { role: data.role },
            { level: data.level },
            { languages: [...data.languages] },
            { tools: [...data.tools] }
          ];

because I want to find out when a tag clicked it belongs to which key of the datas.json

and in

 const filterTag = (key, value) => {
    const newJob = props.datas.filter((job) => job[key].includes(value));
    setJobs(newJob);
  };
 

that I moved it from Card to CardList component the function filtered the datas based on key and value that had been clicked

In line 36 to 48

 {Object.keys(tag).map((m) => {
                if (Array.isArray(tag[m])) {
                  return tag[m].map((n) => (
                    <li onClick={() => props.filterTag(m, n)}>{n}</li>
                  ));
                } else {
                  return (
                    <span onClick={() => props.filterTag(m, tag[m])}>
                      {tag[m]}
                    </span>
                  );
                }
              })}

first I checked if the value is array or not If yes I make list of elements by map on array and if not I just make a single li element. In onClick event I pass the selected key and value to CardList's filterTag function to filter the data

I hope it's helpful.

Sign up to request clarification or add additional context in comments.

4 Comments

The idea is to update my app when I filter by clicking on one of the tags? not filtring my tags !!
Hello Ahmad, thank you for your help, the filter is working, but I didn't understand some lines of the code that you wrote? why did you change the array Tags into an array of objects? and can you please explain more about the code written in the Card component from lines 36 to 48? Thank you
I explain a little more, I hope it's helpful.
Thank you so much Ahmad that was so clear and helpfull
1

So Basically filter always returns an array. You need to return first selected object from that array (which eventually is only one object at index 0). So do as follows:

  const filterTag  = (tag) => {
    const newJob = jobs.filter((job)=> job.tag === tag);
    console.log(newJob[0]);
    setJobs(newJob[0]); // This you need to do
  }

3 Comments

It is not working Imran it giving me an error of "TypeError: Cannot read property 'filter' of undefined", the idea is to update my app when I filter by clicking on one of the tags? Thank you
@DavidJay I am on work right now. Do one thing create a codesandbox project and share the link with me. I can help you out more that way.
Thank you Imran, the problem already got solved :D

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.