Home > Net >  Javascript: Spread array of an object in an object and change properties inside it only
Javascript: Spread array of an object in an object and change properties inside it only

Time:11-26

I have a scenario where I want to change properties of object in an array. That array is wrapped inside another object.


const defaultData = {
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 0,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};

When I spread it like this:

{...defaultData, ...defaultData.books[0], panelsCollected:123} //previously it was 0

then it adds another extra object to parent object but not update it inside first index of books array

How can I just change that panelsCollected property without disturbing whole structure as we are using typescript.

Edit:

We can change it directly accessing the property too as we know index but that comes with a side effect of manipulating original dataset also which we should avoid and only copy needs to be updated.

Thanks

CodePudding user response:

When spreading an object with nested properties with the intention of updating specific properties, think of it in two steps:

  1. Spread the original object to copy it (...)
  2. Redefine the new property values after the spread object

In your example we are doing the following:

  • Duplicating defaultData and assigning an updated books property (to be defined in the next step)
  • Duplicating the first book (defaultData.books[0]) and assigning an updated panelsCollected property to it. Then overwriting the existing books property with this updated array item

The result is as follows:

const defaultData = {
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 0,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};

const newBook = {
  ...defaultData,
  books: [
    {
      ...defaultData.books[0],
      panelsCollected: 123
    }
  ]
}

console.log(newBook)
/*
{
  title: "Title",
  subtitle: "Subtitle",
  books: [
    {
      bookId: "1",
      imageSrc:
        "any.png",
      name: "Issue",
      userOwnsData: true,
      panelsCollected: 123,
      totalPanels: 123,
      link: "https://google.com",
    },
  ],
  bgColor: "black",
};
*/

If for example the books property was 1000 items long, you would instead use have to find the specific book in your array using an array method (e.g. find / findIndex) and update it, e.g.

const bookToUpdateIndex = defaultData.books.findIndex(book => bookId === '1')

const updatedBooks = defaultData.books
updatedBooks[bookToUpdateIndex] = {
  ...updatedBooks[bookToUpdateIndex],
  panelsCollected: 123
}

const newBook = {
  ...defaultData,
  books: updatedBooks
}

CodePudding user response:

I think it is creating another parent object because you are using the spread twice. I tried to do 2 console logs. Please let me know if this is the result you are looking for.

 console.log({...defaultData['books'][0]['panelsCollected'] = 10})
  console.log(defaultData);

CodePudding user response:

Instead of using find and the spread syntax an alternative approach (but not necessarily the most performant) might be to copy the object by stringifying it, and then reparsing that string. And then you can just update the object at the index you need.

const defaultData={title:"Title",subtitle:"Subtitle",books:[{bookId:"1",imageSrc:"any.png",name:"Issue",userOwnsData:!0,panelsCollected:0,totalPanels:123,link:"https://google.com"}],bgColor:"black"};

const copy = JSON.parse(JSON.stringify(defaultData));
copy.books[0].panelsCollected = 123;

console.log(defaultData);
console.log(copy);

  • Related