React 建议不要改变状态。我有一组对象,我根据一些事件来操作它们。我的问题是,这样写可以吗:
const makeCopy = (arr) => arr.map((item) => ({ ...item }));
function SomeComponenet() {
const [filters, setFilters] = useState(aemFilterData);
const handleFilterClick = (filter, c) => {
let copiedFilters = makeCopy(filters);
/**
* Apply toggle on the parent as well
*/
if (!("parentId" in filter)) {
copiedFilters[filter.id].open = !copiedFilters[filter.id].open;
}
setFilters(copiedFilters);
}
}
我是否通过像上面那样改变原始对象?或者如果这样写会有什么不同吗:
const makeCopy = (arr) => arr.map((item) => ({ ...item }));
function SomeComponent() {
const [filters, setFilters] = useState(aemFilterData);
const handleFilterClick = (filter, c) => {
let copiedFilters = makeCopy(filters);
/**
* Apply toggle on the parent as well
*/
if (!("parentId" in filter)) {
copiedFilters = copiedFilters.map((f) => {
if (filter.id === f.id) {
return {
...f,
open: !f.open,
};
} else {
return { ...f };
}
});
}
setFilters(copiedFilters);
}
}
执行此操作的首选方法是什么?扩展运算符变得非常冗长,我不喜欢它,但如果我需要在这里这样做,我更喜欢它。 immutable.js 和 immer 或现在不是一个选项。
const makeCopy = (arr) => arr.map((item) => item );
使用上面的代码,它会在原始对象引用上发生变化,因为我们没有创建深度克隆。
copiedFilters[filter.id].open = !copiedFilters[filter.id].open;
这里
copiedFilters[filter.id]
和filters[filter.id]
的参考是一样的。
带有扩展运算符
const makeCopy = (arr) => arr.map((item) => ({ ...item }));
在这里我们也创建了内部对象的一个新副本。所以
copiedFilters[filter.id]
和filters[filter.id]
会有不同的参考。
这与您的第二种方法相同。
因此,您可以在制作副本时使用扩展运算符,也可以跳过第二种方法中的副本并直接映射到
filters
,因为您在那里使用扩展运算符。这看起来更好,因为为什么运行循环两次 - 首先创建副本,然后更新open
。
// let copiedFilters = makeCopy(filters); Not needed in second approach
copiedFilters = copiedFilters.map((f) => {
if (filter.id === f.id) {
return {
...f,
open: !f.open,
};
} else {
return { ...f };
}
});
您可以在复制时创建深度克隆,但这会浪费计算和内存,我认为这里不需要它。 当您在对象中进一步嵌套时,深度克隆会很有帮助。