0

I am trying to concat new items with existing items to an array that is inside the array. This is how my object look like:

{
   "categories":[
      {
         "category":"cat1",
         "products":[
            {
               "prodname":"product1",
               "quantity":"10"
            },
            {
               "prodname":"product2",
               "quantity":"14"
            }
         ]
      },
      {
         "category":"cat2",
         "products":[
            {
               "prodname":"product3",
               "quantity":"11"
            },
            {
               "prodname":"product4",
               "quantity":"4"
            }
         ]
      }
   ]
}

This is how I update the products array when I get new products in an array for a category.

var indexOfCategory = categoryDataCache.categories.findIndex(c => c.category === "cat1");

    setCategoryDataCache(prevState => ({
      ...prevState,
      categories: [{
          [indexOfCategory]: {
            products: prevState.categories[indexOfCategory].products.concat(newproducts)
          }
        }]
    }))

here are the 2 problems with this code:

  1. it overrides the existing category object as I do not see quantity property after the update
  2. It adds new products as array of products array instead of concatenating the existing products array.

What am I missing here?

1
  • Can you console.log(newproducts) and show it? and Also it looks like you create 1 item categories array? Commented Sep 13, 2020 at 2:44

3 Answers 3

2

to achieve what you are requesting for, following is the code and explantion.

setCategoryDataCache(prevState => ({
  ...prevState,
  categories: prevState.categories.map(cat => {
       if(cat.category === "cat1"){
         return {...cat, products:[...cat.products, ...newProducts]}
       } 
       return cat
}}))

The problems in the code are as follows.

  1. js array.findIndex returns a number index at which predicate matches or -1 otherwise.
  2. When restructuring the prevState and having the categories key immediately below, you are overriding the entire categories attribute value that's why you'll notice my code above, I'm rather using a map and just appended the newProducts(assuming it's an array) directly into the products attribute of the matching category. Otherwise, I simply return the category as is.
  3. If the newProducts object isn't an array, then you should have to spread it ie, remove the ... on ...newProducts.
Sign up to request clarification or add additional context in comments.

Comments

1

I think it should look like this.

var indexOfCategory = categoryDataCache.categories.findIndex(c => c.category === "cat1");

    setCategoryDataCache(prevState => {
      
      let newCats = categories[indexOfCategory] = {
          products: prevState.categories[indexOfCategory].products.concat(newproducts)
      };

      return {
        ...prevState,
        categories: newCats
      }
    })

Comments

1

My choice would be to rather clone the prevState and then return the updated object. Like this

var indexOfCategory = categoryDataCache.categories.findIndex(c => c.category === "cat1");

    setCategoryDataCache(prevState => {
      const CDC = {...prevState};
      CDC.categories[indexOfCategory].products = CDC.categories[indexOfCategory].products.concat(newproducts);
      return CDC;
    })

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.