Reputation: 279
I am creating an e-commerce app and on the Shop page I want to implement filters based on category and price. I have set the state like so:
const [filters, setFilters] = useState({
cat: "",
price: "",
});
And this is the select tag and the options to trigger the change for the category:
<select className="outline-none" name="category" onChange={handleChange}>
<option value="start">-</option>
<option value="Hoodie">Hoodie</option>
<option value="T-Shirt">T-Shirt</option>
<option value="Sweatshirt">Sweatshirt</option>
</select>
This is the handleChange
method:
const handleChange = (e) => {
const value = e.target.value;
if (value === "start") {
setProductsF(products);
} else {
setFilters((prevFilters) => ({ ...prevFilters, cat: value }));
const testArr = [...products];
const filteredProd = testArr.filter(
(prod) => prod.categories[0].name === filters.cat
);
setProductsF(filteredProd);
}
}
The problem is, when the handleChange
fires the filters get the previous value and are not updated correctly. Let's say I change the values to "Hoodie" then "T-Shirt". When I click on "Hoodie" the shopping list is empty and when I click on "T-Shirt", I get the list of hoodies. I get the products from static props and I am setting the filtered products on this state:
const [productsF, setProductsF] = useState(products);
What is the way to get the correct filters values when the user selects an option?
Upvotes: 1
Views: 2707
Reputation: 23161
You try to use the updated filters
state right after you "updated" it. Don't forget that useState
is asynchronous just like setState
in class components. You can't update the state on one line and assume it's already changed on the next one. You'll likely use the unchanged state.
Instead of filters.cat
, you can use the value
you receive. This way you update both the filters
and the productsF
state.
const handleChange = (e) => {
const value = e.target.value;
if (value === 'start') {
setProductsF(products);
} else {
setFilters((prevFilters) => ({ ...prevFilters, cat: value }));
const testArr = [...products];
const filteredProd = testArr.filter(
(prod) => prod.categories[0].name === value,
);
setProductsF(filteredProd);
}
};
Upvotes: 2