Reputation: 353
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"]
}
]
Upvotes: 0
Views: 187
Reputation: 884
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.
Upvotes: 1
Reputation: 8078
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
}
Upvotes: 1