Reputation: 67
I'm making a simple React app where I am getting a list of cars through useEffect hook and then mapping through each one to display them on the screen. Then, I have one button whose purpose would be to sort the cars based on their horsepower. So, when clicking on that button the user would see only the cars whose horsepower is greater than for example 700.
import React, { useState, useEffect } from "react";
import "./style.css";
export default function App() {
const [items, setItems] = useState([])
const [yo, setYo] = useState(false)
useEffect(() => {
fetch("https://private-anon-af560a53c6-carsapi1.apiary-mock.com/cars")
.then(res => res.json())
.then(data => {
setItems(data)
})
}, [])
function reverse(){
items.reverse();
setItems([...items])
}
function sortHigherHP(){
let cars = items.filter(item => {
return item.horsepower >= 700;
}).map(i => {
return(
<div key={Math.floor(Math.random()*10000)} style={{border: "1px solid black", margin: "10px", padding: "5px"}}>
<p>Make: {i.make}</p>
<p>Horsepower: {i.horsepower} HS</p>
</div>
)
});
setItems(cars)
}
function hey(){
setYo(!yo)
}
return (
<div>
<h1>React Search & Filter</h1>
<div>
<h3 onClick={hey}>Sort</h3>
<div className={yo ? "show" : "hide"}>Sorting options
<button onClick={reverse}>Reverse Order</button>
<button onClick={sortHigherHP}>Higher Horsepower</button>
</div>
</div>
{items.slice(0, 50).map(a => {
return (
<div key={Math.floor(Math.random()*10000)} style={{border: "1px solid black", margin: "10px", padding: "5px"}}>
<p>Make: {a.make}</p>
<p>Horsepower: {a.horsepower} HS</p>
</div>
)
})}
</div>
);
}
The reverse event handler is obviously working since the reverse method just reverses the array, without changing the original array. But this filter method returns a new array and I have problems here on how to actually display data on the screen. Could the problem be in the .map method that comes right after .filter()?
Upvotes: 1
Views: 184
Reputation: 15462
Could the problem be in the .map method that comes right after .filter()?
Yes this is indeed the problem:
function sortHigherHP() {
let cars = items
.filter((item) => {
return item.horsepower >= 700;
})
.map((i) => {
return (
<div
key={Math.floor(Math.random() * 10000)}
style={{
border: "1px solid black",
margin: "10px",
padding: "5px",
}}
>
<p>Make: {i.make}</p>
<p>Horsepower: {i.horsepower} HS</p>
</div>
);
});
setItems(cars);
}
You should remove the map in its entirety here:
function sortHigherHP() {
let cars = items.filter((item) => {
return item.horsepower >= 700;
});
setItems(cars);
}
You already have a map
call that handles displaying your items:
{
items.slice(0, 50).map((a) => {
return (
<div
key={Math.floor(Math.random() * 10000)}
style={{
border: "1px solid black",
margin: "10px",
padding: "5px",
}}
>
<p>Make: {a.make}</p>
<p>Horsepower: {a.horsepower} HS</p>
</div>
);
});
}
Because of the extra map
call you're actually setting the items
state to jsx
instead of an array of objects, which makes the code above not work.
Upvotes: 1