У меня есть сценарий, в котором я хочу изменить свойства объекта в массиве. Этот массив заключен в другой объект.
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",
};
Когда я распространяю это так:
{...defaultData, ...defaultData.books[0], panelsCollected:123} //previously it was 0
затем он добавляет еще один дополнительный объект к родительскому объекту, но не обновляет его внутри первого индекса массива книг
Как я могу просто изменить это свойство panelCollected, не нарушая всей структуры, поскольку мы используем машинописный текст.
Редактировать:
Мы также можем изменить его, напрямую обращаясь к свойству, поскольку мы знаем индекс, но это имеет побочный эффект манипулирования исходным набором данных, которого также следует избегать, и нужно обновлять только копию.
Спасибо
@Andy Да, это изменит только одно свойство, но как насчет других данных, которые нам нужны. Как я могу получить ту же структуру с изменением только одного свойства.
Какие еще данные? Вероятно, вам следует расширить код вопроса, чтобы он отражал проблему, с которой вы столкнулись.
@Энди, у меня есть объект с именем defaultData
, и я хочу вернуть его ту же структуру, но нужно обновить только одно свойство, которое было panelsCollected
. Я старался изо всех сил, чтобы очистить все, о чем идет речь.
Если вы знаете индекс объекта в книгах, вы можете просто обновить значение этого свойства, как я предложил. Вам не обязательно создавать новый объект, распространяя старый.
@ Andy То, что вы упоминаете, имеет побочный эффект, заключающийся в том, что он также будет манипулировать исходным набором данных. При этом мы хотим, чтобы при мутации объектов, как правило, обновлялась только его копия. Вопрос обновлен с большей конкретикой.
При распространении объекта с вложенными свойствами с целью обновления конкретных свойств подумайте об этом в два этапа:
...
)В вашем примере мы делаем следующее:
defaultData
и назначение обновленного свойства books
(будет определено на следующем шаге)defaultData.books[0]
) и присвоение ей обновленного свойства panelsCollected
. Затем перезапишите существующее свойство books
этим обновленным элементом массива.Результат выглядит следующим образом:
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.info(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",
};
*/
Если, например, свойство books
имеет длину 1000 элементов, вместо этого вам нужно будет найти конкретную книгу в вашем массиве с помощью метода массива (например, find
/ findIndex
) и обновить его, например.
const bookToUpdateIndex = defaultData.books.findIndex(book => book.bookId === '1')
const updatedBooks = [...defaultData.books]
updatedBooks[bookToUpdateIndex] = {
...updatedBooks[bookToUpdateIndex],
panelsCollected: 123
}
const newBook = {
...defaultData,
books: updatedBooks
}
findIndex(book => bookId === '1')
должно быть findIndex(book => book.bookId === '1')
А также этот ответ также мутирует исходный объект. @SulemanAhmad, это не то, что ты хотел.
Вместо использования find
и синтаксиса расширения альтернативный подход (но не обязательно самый эффективный) может состоять в том, чтобы скопировать объект, преобразовав его в строку, а затем повторно проанализировав эту строку. И тогда вы можете просто обновить объект по нужному вам индексу.
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.info(defaultData);
console.info(copy);
const newBook = { ...defaultData, books: [ { ...defaultData.books[0], panelCollected: 123 } ] }
Я искал эту часть, которая не мутирует исходный объект.
Но это работает, только если у вас есть одна книга. @СулеманАхмад. Я указывал на вторую часть этого ответа, которая мутировала исходный объект.
Зачем вам нужно распространять этот объект, чтобы обновить одно значение? Почему бы не просто
defaultData.books[0].panelsCollected = 123
?