Reputation: 47
I have array of objects products
like
[{name: 'apple', value: 100}, {name: 'watermelon', value: 200}, {name: 'orange', value: 50}]
, and a select input with "High price" and "Low price" options, but it doesn't works:
function ProductsPage() {
const [products, setProducts] = useState([])
useEffect(() => {/*here i setProducts([...]) array of objects which i get of backend*/})
const orderShowing = (e) => {
let actual_show = products
let newOrder = e.target.value;
if (newOrder === "High price") {
actual_show.sort((a, b) => (b.value > a.value) ? 1 : (a.value > b.value) ? -1 : 0)
} else if (newOrder === "Low price") {
actual_show.sort((a, b) => (a.value > b.value) ? 1 : (b.value > a.value) ? -1 : 0)
console.log(actual_show)
setProducts(actual_show)
}
return (
<div>
<select id="productsOrder" onChange={orderShowing}>
<option>High price</option>
<option>Low price</option>
</select>
<h2>Products</h2>
{products.map((p) => {
return <p>{p.name}</p>})}
</div>
)
}
the console.log actually is what i want (the sort works), but the page don't refresh with the 'new' products
array
Upvotes: 3
Views: 158
Reputation: 1985
Here's the working example with minimum changes to the existing code. Run the code here
export default function App() {
const [products, setProducts] = useState([]);
useEffect(() => {
setProducts([
{ name: 'apple', value: 100 },
{ name: 'watermelon', value: 200 },
{ name: 'orange', value: 50 }
]);
}, []);
const orderShowing = e => {
let actual_show = products.slice(); //making a copy of products
let newOrder = e.target.value;
if (newOrder === 'High price') {
actual_show.sort((a, b) =>
b.value > a.value ? 1 : a.value > b.value ? -1 : 0
);
} else if (newOrder === 'Low price') {
actual_show.sort((a, b) =>
a.value > b.value ? 1 : b.value > a.value ? -1 : 0
);
}
console.log(actual_show);
setProducts(actual_show);
};
return (
<div>
<select id="productsOrder" onChange={orderShowing}>
<option>High price</option>
<option>Low price</option>
</select>
<h2>Products</h2>
{products.map(p => {
return <p>{p.name}</p>;
})}
</div>
);
}
Upvotes: 1
Reputation: 4974
First you need to make a copy of your state
:
let actual_show = [...products];
Then try to sort it like I'm using :
import { useEffect, useState } from "react";
export default function App() {
const [products, setProducts] = useState([
{ name: "apple", value: 100 },
{ name: "watermelon", value: 200 },
{ name: "orange", value: 50 }
]);
const orderShowing = (e) => {
let actual_show = [...products];
let newOrder = e.target.value;
if (newOrder === "High price") {
actual_show.sort((a, b) => a.value - b.value);
} else if (newOrder === "Low price") {
actual_show.sort((a, b) => b.value - a.value);
}
setProducts(actual_show);
};
return (
<div>
<select id="productsOrder" onChange={orderShowing}>
<option>High price</option>
<option>Low price</option>
</select>
<h2>Products</h2>
{products.map((p) => {
return <p>{p.name}</p>;
})}
</div>
);
}
Upvotes: 3
Reputation: 1
I ran your code. You just forgot the curly braces on p.name when you mapped it - it will be treated as a string otherwise. It should be {p.name}.
Upvotes: 0
Reputation: 11
Try something like this:
products.sort(function (a, b) {
return a.value - b.value;
});
Keep in mind this solution will only work since the values are numeric.
Upvotes: -1