Reputation: 81
I am trying to update the state with an array. But I need to keep the existing information in the array and just push more information into it.
Here is my state:
const [filteredProducts, setFilteredProducts] = useState([]);
This is my function I am calling for the onClick event listener
const filteredByCategory = (event, category, products) => {
const element = document.getElementById(event.target.id);
if (element.checked) {
const productsToAdd = products.filter(
(product) => product.category === category
);
setFilteredProducts((currentFilteredProducts) => [
...currentFilteredProducts,
...productsToAdd,
]);
dispatch({
type: "PRODUCTS_FILTERED",
payload: filteredProducts,
});
} else {
let removedCheckedProducts = filteredProducts.filter((product) => {
return product.category !== category;
});
setFilteredProducts(removedCheckedProducts);
if (removedCheckedProducts.length >= 1) {
dispatch({
type: "PRODUCTS_FILTERED",
payload: removedCheckedProducts,
});
} else {
dispatch({
type: "PRODUCTS_FILTERED",
payload: allProducts,
});
}
}
};
Upvotes: 1
Views: 143
Reputation: 1365
digitalbreed identified the race condition correctly in his answer. An example of this behavior can be seen in this code sandbox by viewing the console after clicking the addProduct
button
Upvotes: 0
Reputation: 4070
My assumption is that you expect the filteredProducts
state value to reflect your changes right after setFilteredProducts
:
setFilteredProducts((currentFilteredProducts) => [
...currentFilteredProducts,
...productsToAdd,
]);
dispatch({
type: "PRODUCTS_FILTERED",
payload: filteredProducts,
});
Unfortunately, that's not how state updates work. The set*
function simply queues the update for the next render, but does not immediately update the state.
You could maintain a local variable to pass the update both into the local state and into the Redux store:
const updatedProducts = [
...filteredProducts,
...productsToAdd,
];
setFilteredProducts(updatedProducts);
dispatch({
type: "PRODUCTS_FILTERED",
payload: updatedProducts,
});
Upvotes: 2