首页 > 解决方案 > 在数组 redux 中更新数组

问题描述

我有一个嵌套数组的状态,如下所示:

{
    list: [
        {
        id: '3546f44b-457e-4f87-95f6-c6717830294b',
        title: 'First Nest',
        key: '0',
        children: [
            {
            id: '71f034ea-478b-4f33-9dad-3685dab09171',
            title: 'Second Nest',
            key: '0-0
            children: [
                {
                id: '11d338c6-f222-4701-98d0-3e3572009d8f',
                title: 'Q. Third Nest',
                key: '0-0-0',
                }
            ],
            }
        ],
    ],
    selectedItemKey: '0'
}

嵌套数组的目标是模仿树,而 selectedItemKey/key 是如何快速访问树节点。

我编写了代码来使用以下逻辑更新嵌套项的标题:

let list = [...state.list];
let keyArr = state.selectedItemKey.split('-');
let idx = keyArr.shift();
let currItemArr = list;

while (keyArr.length > 0) {
  currItemArr = currItemArr[idx].children;
  idx = keyArr.shift();
}

currItemArr[idx] = {
  ...currItemArr[idx],
  title: action.payload
};

return {
  ...state,
  list
};

第一个嵌套项的工作正常,但对于第二级和第三级嵌套,我收到以下 Immer 控制台错误

An immer producer returned a new value *and* modified its draft.
Either return a new value *or* modify the draft.

关于嵌套数组访问/更新逻辑,或者我试图制作 state.list 的新副本并对其进行修改的方式,我觉得我在这里搞砸了一些相当大的事情。请注意嵌套级别是动态的,在修改它之前我不知道它的深度。

再次提前感谢!

标签: reduxredux-toolkit

解决方案


Immer 允许您修改现有草稿statereturn新状态,但不能同时修改两者。

看起来您正在尝试返回一个新状态,只要没有突变就可以了。但是,您在分配时进行了修改currItemArr[idx] = 。这是一个突变,因为 和 的元素listcurrItemArr中的元素相同state.list。这是一个“浅拷贝”。

但是您不必担心浅拷贝和突变,因为更简单的方法是只修改草稿状态而不返回任何内容。

您只需要找到正确的对象并设置其title属性即可。我想出了一个更短的方法来使用array.reduce().

const keyArr = state.selectedItemKey.split("-");

const target = keyArr.reduce(
  (accumulator, idx) => accumulator.children[idx],
  { children: state.list }
);

target.title = action.payload;

推荐阅读