If I have this array:
const data = [
{
id: 1,
category: "ladders",
name: "N/A",
price: 0,
},
{
id: 2,
category: "ladders",
name: "Ladder 1",
price: 220,
},
{
id: 3,
category: "ladders",
name: "Ladder 2",
price: 420,
},
{
id: 4,
category: "ladders",
name: "Ladder 3",
price: 515,
},
]
And I have this in my useState hook:
const [selections, setSelections] = useState({
ladders: [2, 4]
});
I'm trying to output in my JSX the values of the objects in data
that have a matching 'id' to the values in my 'ladders' property in my useState hook (i.e. 2 and 4). I can do it by manually specifying the array indexes, like so:
{data
.filter((item) => item.id === selections.ladders[0])
.map((item) => {
return (
<li className="item" key={item.id}>
<div className="item__body">
<h3 className="item__name">{item.name}</h3>
</div>
<span className="item__price">£{item.price}</span>
</li>
);
})}
{data
.filter((item) => item.id === selections.ladders[1])
.map((item) => {
return (
<li className="item" key={item.id}>
<div className="item__body">
<h3 className="item__name">{item.name}</h3>
</div>
<span className="item__price">£{item.price}</span>
</li>
);
})}
But how I can refactor this so I don't have to manually specify the 'ladders' array indexes? Any help appreciated.
CodePudding user response:
Just check whether ladders
includes the ID:
.filter((item) => selections.ladders.includes(item.id))
CodePudding user response:
You can use Array.prototype.includes
.
{data
.filter((item) => selections.ladders.includes(item.id))
.map((item) => {
return (
<li className="item" key={item.id}>
<div className="item__body">
<h3 className="item__name">{item.name}</h3>
</div>
<span className="item__price">£{item.price}</span>
</li>
);
})}
If you can change the structure of data
, you can actually change it to an object for a bit more performance.
{
"1": {
"id": 1,
"category": "ladders",
"name": "N/A",
"price": 0
},
"2": {
"id": 2,
"category": "ladders",
"name": "Ladder 1",
"price": 220
},
"3": {
"id": 3,
"category": "ladders",
"name": "Ladder 2",
"price": 420
},
"4": {
"id": 4,
"category": "ladders",
"name": "Ladder 3",
"price": 515
}
}
Then you can do setSelected(prev=>[...prev, item.id])
. And for rendering:
{selected
.map((id) => {
return (
<li className="item" key={id}>
<div className="item__body">
<h3 className="item__name">{data[id].name}</h3>
</div>
<span className="item__price">£{data[id].price}</span>
</li>
);
})}
If you don't have access to data, you can use a Set
. Checking if an element is in a set is O(1)
as compared to O(n)
for Array.includes
.