React - 深拷贝数组和对象问题
React - deep copy arrays and objects problem
我有一个状态数组,我想对其执行操作然后更新状态,但似乎我在某处缺少深层副本并且状态在没有 setState 的情况下更新,这导致我出现问题(我知道因为我看到即使没有 setState 行状态也会更新)。
const itemsToRemove = ['Pepsi', 'Fanta'];
let temp = [...this.state.categories];
let categoryToUpdate = temp.find((category) => category.name == 'drinks');
categoryToUpdate.items = categoryToUpdate.items.filter((item) => {
return !itemsToRemove.includes(item);
});
//this.setState({categories: temp})
在这些行之后,我希望 categories
名称为“drinks”的对象中的状态仍然包含 itemsToRemove
中的项目,因为我没有更新状态,但它们仍然会从状态中删除.
categories
状态结构如下:
categories:[{name: String, items: Object}...]
你猜对了,当你直接更新copy.items
时,你仍然改变了items
数组。尽管您使用了扩展运算符,但它只深入了一层。它只创建数组的浅表副本。
它适用于基本数据类型(字符串、数字等),但是当您有嵌套对象(数组)并复制它时,该对象内的这些嵌套对象将不会被复制,因为它们只是引用。
const original = [{
name: 'Name 1',
items: ['1', '2', '3']
}, {
name: 'Name 2',
items: ['11', '12', '13']
}, 99]
const copy = [...original]
// notice how the original third element won't change to 100
copy[2] = 100
// while all the items in the second element will
copy[1].items = ['21', '22', '23']
// and if you update a string inside the object
// that will be changed too as it's inside an object
copy[1].name = 'Updated name 2'
console.log('updated', copy)
console.log('original', original)
您可以使用 Array.map()
从 categories
数组创建一个新数组,当您遍历元素时,您可以简单地 return 使用扩展运算符创建一个新对象,如果你想更新它们。
检查下面的代码片段:
const itemsToRemove = ['Pepsi', 'Fanta'];
const categories = [{
name: 'drinks',
items: ['1', '2', 'Pepsi', '4', 'Fanta', '6']
},
{
name: 'biscuits',
items: ['1', '2', '3', '4']
},
];
const updatedCategories = categories.map((category) =>
category.name === 'drinks'
? {
...category,
items: category.items.filter((item) => !itemsToRemove.includes(item)),
}
: category,
);
console.log('updated', updatedCategories);
console.log('original', categories);
我有一个状态数组,我想对其执行操作然后更新状态,但似乎我在某处缺少深层副本并且状态在没有 setState 的情况下更新,这导致我出现问题(我知道因为我看到即使没有 setState 行状态也会更新)。
const itemsToRemove = ['Pepsi', 'Fanta'];
let temp = [...this.state.categories];
let categoryToUpdate = temp.find((category) => category.name == 'drinks');
categoryToUpdate.items = categoryToUpdate.items.filter((item) => {
return !itemsToRemove.includes(item);
});
//this.setState({categories: temp})
在这些行之后,我希望 categories
名称为“drinks”的对象中的状态仍然包含 itemsToRemove
中的项目,因为我没有更新状态,但它们仍然会从状态中删除.
categories
状态结构如下:
categories:[{name: String, items: Object}...]
你猜对了,当你直接更新copy.items
时,你仍然改变了items
数组。尽管您使用了扩展运算符,但它只深入了一层。它只创建数组的浅表副本。
它适用于基本数据类型(字符串、数字等),但是当您有嵌套对象(数组)并复制它时,该对象内的这些嵌套对象将不会被复制,因为它们只是引用。
const original = [{
name: 'Name 1',
items: ['1', '2', '3']
}, {
name: 'Name 2',
items: ['11', '12', '13']
}, 99]
const copy = [...original]
// notice how the original third element won't change to 100
copy[2] = 100
// while all the items in the second element will
copy[1].items = ['21', '22', '23']
// and if you update a string inside the object
// that will be changed too as it's inside an object
copy[1].name = 'Updated name 2'
console.log('updated', copy)
console.log('original', original)
您可以使用 Array.map()
从 categories
数组创建一个新数组,当您遍历元素时,您可以简单地 return 使用扩展运算符创建一个新对象,如果你想更新它们。
检查下面的代码片段:
const itemsToRemove = ['Pepsi', 'Fanta'];
const categories = [{
name: 'drinks',
items: ['1', '2', 'Pepsi', '4', 'Fanta', '6']
},
{
name: 'biscuits',
items: ['1', '2', '3', '4']
},
];
const updatedCategories = categories.map((category) =>
category.name === 'drinks'
? {
...category,
items: category.items.filter((item) => !itemsToRemove.includes(item)),
}
: category,
);
console.log('updated', updatedCategories);
console.log('original', categories);