Ваш resultsRooms.map
не так. Прежде всего, он не возвращает объект. Если вы используете функцию со стрелкой и хотите вернуть объект, вы должны заключить его в скобки.
const foo = () => ( { foo: "bar" } );
Если вы этого не сделаете, функция увидит {}
как блок тела.
Ваша вторая проблема: map
возвращает массив, не выполняет операций с элементами. Так что вы не можете сделать это: room.sunday.flag = true;
Вот рабочая версия:
const rooms = resultsRooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Итак, мы отображаем комнаты, а затем возвращаем объект с расширенным синтаксисом. С ...room
мы сохраняем части room
, отличные от sunday
объекта. С sunday: {...room["sunday"], flag: true }
мы сохраняем части sunday
, отличные от свойства flag
. Кроме того, на самом деле нам не нужно делать копию с:
const resultsRooms = [
...this.state.results[0].rooms ];
Поскольку мы не изменяем его, с помощью map
мы создаем новый массив. Итак, вот последняя версия:
const rooms = results[0].rooms.map((room, roomIndex) =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
Эта часть в порядке, мы не изменяем состояние, но если вы используете forEach
на results
, вы изменяете исходные данные. Не делай этого.
Вот краткая и, возможно, более чистая альтернатива без использования forEach
.
const newRooms = results[0].rooms.map( room =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
const newItem = { ...results[0], rooms: newRooms };
const newResults = Object.assign([], results, { 0: newItem } );
Обновление после комментариев
Я использовал Object.assign
здесь, чтобы заменить элемент без изменения исходного массива. При использовании React (также, если вы предпочитаете использовать с React, это также относится и к Redux), мы должны избегать изменения наших данных, а именно нашего состояния. Поэтому, когда вы планируете что-то изменить в состоянии, вы должны делать это надлежащим образом. Ваш вопрос на самом деле указывает на то, что: "без мутирования" Вот почему я использовал Object.assign
здесь.
Я мог бы выбрать другие методы, такие как:
const newResults = results.slice();
newResults[ 0 ] = newItem;
или
const newResults = [ ...results ];
newResults[ 0 ] = newItem;
Это нормально только для замены элемента в целом . Что я имею в виду здесь? slice
и spread syntax
не создают глубокие копии, они просто делают мелкие копии. Если вы измените свойство объекта во вновь созданном массиве, исходный объект также будет видоизменяться. Это также относится к объектам, когда мы меняем вложенные свойства. На самом деле, оригинальный источник - это объекты здесь.
Вот пример массива:
const arr = [
{ id:1, name:"foo" },
{ id:2, name:"bar" },
{ id:3, name:"baz" },
];
и пример элемента, который нужно изменить для индекса 2 (последний элемент здесь);
const newItem = { id: 100, name: "change" };
const newArr = [ ...arr ];
arr[ 2 ] = newItem;
Это нормально, так как здесь мы меняем целый объект. Посмотрим:
const arr = [
{ id:1, name:"foo" },
{ id:2, name:"bar" },
{ id:3, name:"baz" },
];
const newItem = { id: 100, name: "change" };
const newArr = [ ...arr ];
newArr[ 2 ] = newItem;
console.log("new array", newArr );
console.log( "original array", arr );
Оригинал не меняется. Но если мы сделаем это:
newArr[ 2 ].id = 100; // ie, we only want to change the id, right?
Посмотрим:
const arr = [
{ id:1, name:"foo" },
{ id:2, name:"bar" },
{ id:3, name:"baz" },
];
const newArr = [ ...arr ];
newArr[ 2 ].id = 100;
console.log("new array", newArr );
console.log( "original array", arr );
Итак, наш исходный массив также изменился. Мутация! Если вы не измените какое-либо свойство, как это, вы можете выбрать один из трех вариантов. Но если вы поменяете свойство, вам следует подумать о чем-то лучше.
const arr = [
{ id:1, name:"foo" },
{ id:2, name:"bar" },
{ id:3, name:"baz" },
];
const newArr = Object.assign( [], arr, { 2: { ...arr[ 2 ], id: 100 } } );
console.log("new array", newArr );
console.log( "original array", arr );
Duh! :) Может быть, есть лучшие способы сделать это :) В любом случае, будьте очень осторожны с изменением состояния.
Просто с объектом:
const obj = {
user: {
id: 1,
name: "foo",
}
};
const newObj = { ...obj }
newObj.user.id = 1000
console.log( "new object", newObj );
console.log( "original object", obj );
Хорошо, этого достаточно для объяснения:)
Спасибо за ответ. Я немного смущен, я должен установить
состояние выглядит следующим образом: this.setState ({results: newResults});
Да.
также, что если я хочу изменить состояние всех комнат массива результатов
результаты [0], результаты [1], результаты [2] .....
Да ладно, у вас здесь отличный инструмент :) map
const newResults = results.map( item => {
const newRooms = item.rooms.map( room =>
( { ...room, sunday: {...room["sunday"], flag: true } } )
);
const newItem = { ...item, rooms: newRooms };
return newItem;
})
Сначала мы сопоставляем results
, для каждого элемента мы сопоставляем rooms
и меняем данные, возвращая новый элемент. Таким образом, в конце мы получаем новый массив, в котором все его элементы изменились, но снова без каких-либо изменений.
Я предлагаю немного поиграть с map
, filter
и, возможно, reduce
методами. Также ищите spread syntax
или, если вы предпочитаете Object.assign
, это плюс.