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 };
  }
});

你可以在复制的时候创建一个深度克隆,但是那会浪费计算和内存,我认为这里不需要。 当您在对象中进一步嵌套时,深度克隆很有用。