React 上的 JS 传播运算符工作流程
JS spread operator workflow on React
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 是否沉浸现在是一个选项。
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 };
}
});
你可以在复制的时候创建一个深度克隆,但是那会浪费计算和内存,我认为这里不需要。
当您在对象中进一步嵌套时,深度克隆很有用。
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 是否沉浸现在是一个选项。
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 };
}
});
你可以在复制的时候创建一个深度克隆,但是那会浪费计算和内存,我认为这里不需要。 当您在对象中进一步嵌套时,深度克隆很有用。