正在改变这个减速器中的状态吗?

Am in mutating the state in this reducer?

我一直在阅读有关避免改变状态的不同方法。其中一种方法是使用扩展运算符 (...),避免使用的方法之一是推送。然而,在我的 reducer 中,我需要将一个项目添加到嵌套结构内的数组中,我无法正确实现 concat,所以我尝试了以下代码:

export default function (state=[],action){
 if (action.type === 'SELECTED_DROP') {   
     let updated = [ ...state];
     updated[action.payload.queryIndex].items.push(action.payload.item) ;   
     return updated; 
  }
return state;
}

因此,我同时使用:传播运算符和推送。我在改变状态吗?

谢谢

是的,你正在改变状态。据我所知,您的状态是一个数组,其中包含一个 属性 项目的对象,这也是一个数组。您正在修改项目数组,因此您正在改变状态。

这是你应该做的:

export default function (state=[], action) {
  switch (action.type) {
    case 'SELECTED_DROP':
      return state.map((item,ix) =>
        ix===action.payload.queryIndex ?
          {...item, items:[...item.items, action.payload.item]} :
          item
      );
    case default:
      return state;
  }
}

map 函数基本上 returns 旧项目如果没有改变或者新项目与新项目数组如果它是正确的索引。

是的,你绝对是。您正在制作顶级数组的浅表副本,但直接改变了内部数组。

不可变更新数据有两个基本规则:

  • 每一层嵌套都需要复制一份
  • 您可以使用变异,但是 仅当您对实际副本进行变异时

在这种情况下,您需要复制顶部数组,该索引处的项目, items 数组本身。嵌套更新可能有点难看,但事实就是如此。

我在 react-redux-links, and links to a number of utility libraries for abstracting out those updates at react-redux-links & Immutable Update Utilities 上有许多关于如何正确编写不可变更新代码的文章的链接。