使用 redux 为大型状态设计高效的减速器

Designing an efficient reducer for a large state with redux

我正在为我的应用程序使用 redux 和 react 和 typescript。我正在处理在我的应用程序的不同位置使用的许多项目。我的状态是这样的:

{
    items: {42: {}, 53: {}, ... }, //A large dictionary of items
    itemPage1: {
        items: [42, 34, 67, ...],
        ...
    },
    itemPage2: { ... 
    },
    ...
}

我想写一个高效的 item reducer,但是 items 很大,我不能每次都创建深拷贝。显然我不需要根据 gaearon(摘自 there):Redux 不要求您深入克隆每个动作的状态。它只是要求您 return 为已更改的部分创建新对象。您可以为树的任何未更改部分重用以前的状态。 .

太棒了!但是我对这一切都不熟悉,我不确定如何正确实施减速器。到目前为止,我的 item reducer 中的内容是:

case UPDATE_ITEM_LABEL:
    return (<any>Object).assign({}, state, {
          item_id: (<any>Object).assign({}, state[action.item_id], {
              label: action.value
          })
    })

因此它将旧状态的所有元素复制到一个新对象中,然后将结果与具有新更新值的更改对象合并。我希望第一个 assign 期间的项目是通过引用传递的,因此不会被深度复制?如果是这种情况就好了,因为我可以深入复制一个项目和每个操作的一些简单参考。我还发现可以使用 immutable.js 来回答这个问题,如果我提出的方法有效,为什么人们会使用 immutable.js ?

我已经进行了快速测试,以确保我的方法能够完成工作:

var item1 = {prop1: 'item1', prop2: 'haha'};
var item2 = {prop1: 'item2', prop2: 'hehe'};
var items = {1:item1, 2:item2};

console.log(items);

此显示符合预期:

[object Object] {
  1: [object Object] {
    prop1: "item1",
    prop2: "haha"
  },
  2: [object Object] {
    prop1: "item2",
    prop2: "hehe"
  }
}

现在我们使用assign获取下一个状态,修改item2的其中一个键:

var items = Object.assign({},items, { 2: Object.assign({}, items[2],
    {
        prop2: 'huhu' 
    })
});

console.log(items);

此显示符合预期:

[object Object] {
  1: [object Object] {
    prop1: "item1",
    prop2: "haha"
  },
  2: [object Object] {
    prop1: "item2",
    prop2: "huhu"
  }
}

现在有趣的一点是,如果我们使用对 item1 和 item2 的初始引用来更改 prop1 属性:

item1.prop1 = 'ITEM1'
item2.prop1 = 'ITEM2'

console.log(items);

我们发现只有item2被深度复制,这就是我想要的行为:

[object Object] {
  1: [object Object] {
    prop1: "ITEM1",
    prop2: "haha"
 },
  2: [object Object] {
    prop1: "item2",
    prop2: "huhu"
  }
}