3

I have a state set as

const [filteredProducts, setFilteredProducts] = useState([]);

I want to be able to append to the end of that state. I am currently trying

products.forEach((product) => {
        if (product.category === category) {
          setFilteredProducts([...filteredProducts, product]);
        }
      });

It it looping through the products array correctly. I can even log the product after the setFilteredProducts and it logs the correct ones I want. I am calling this with an onClick.

1
  • You're stacking up setState calls, instead create the new filtered array and then call setState once Commented Aug 18, 2021 at 23:21

5 Answers 5

5

Find all the products you want to add:

const productsToAdd = products.filter(product => product.category === category)

Then append them

setFilteredProducts((currentFilteredProducts) => ([...currentFilteredProducts, ...productsToAdd]));

The issue with your example is that filteredProducts may get stale after the first iteration. setFilteredProducts will not run synchronously, and filteredProducts keep the original value, until the re-render happen.

Sign up to request clarification or add additional context in comments.

Comments

1

You would only append the last match to the existing filteredProducts array.

You can add all matches like so:

setFilteredProducts([...filteredProducts, ...products.filter((product) => product.category === category)]);

Comments

0

I'd recommend you do this in 2 steps:

Create an array of the new products you plan to add

let productsToAdd = [];

products.forEach((product) => {
    if (product.category === category) {
      productsToAdd.push(product);
    }
  });

Then combine the arrays and set state

setFilteredProducts([...filteredProducts, ...productsToAdd]);

Comments

0

I think you want what the ES6 built-in function does. You can rewrite your code to give you the the products that match the category like this:

const filteringTheProducts = products.filter(product => {
    return product.category === category
})

setFilteredProducts(filteringTheProducts)

The result of the filtering will be the array of all the products that match that criteria.

Here is the documentation for .filter() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

Comments

0

The problem is, that setFilteredProducts doesn't immediately affect products. It's React's job to decide when to update the state. So when you loop over products, you'll probably ending up adding just the last item, because filteredProducts wasn't updated yet. What you can do, is preparing an array of products to add:

const productsToAdd = products.filter(product => product.category === category);

And then append them:

setFilteredProducts([...products, ...productsToAdd]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.