我在改变这个减速器的状态?

时间:2016-09-19 19:53:37

标签: redux immutability react-redux

我一直在阅读有关避免改变状态的不同方法。其中一种方法是使用扩展运算符(...),其中一种方法是避免使用推送。但是在我的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;
}

所以,我正在使用:spread operator和push。我是在改变状态吗?

谢谢

2 个答案:

答案 0 :(得分:2)

是的,你正在改变国家。根据我收集的内容,您的状态是一个包含属性项的对象的数组,该属性项也是一个数组。您正在修改items数组,因此您正在改变状态。

这是你应该做的:

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函数基本上返回旧项目(如果没有更改)或新项目带有新项目数组(如果它是正确的索引)。

答案 1 :(得分:0)

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

有两种不可更新数据的基本规则:

  • 每个级别的嵌套都需要制作副本
  • 您可以使用变异,但如果您正在改变实际副本

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

我有许多关于如何在https://github.com/markerikson/react-redux-links/blob/master/immutable-data.md正确编写不可变更新代码的文章的链接,以及指向许多实用程序库的链接,用于在https://github.com/markerikson/redux-ecosystem-links/blob/master/immutable-data.md#immutable-update-utilities抽象出这些更新。