简体   繁体   English

在不改变状态的情况下根据减速器中的给定索引更改嵌套数组值

[英]Changing a nested array value based on a given index in a reducer while not mutating state

I have a reducer working with an object with arrays.我有一个减速器处理一个带有数组的对象。 I want to change a value on the nested arrays based on a given index.我想根据给定的索引更改嵌套数组上的值。 This code works but I can't seem to get my test to work using deep freeze.此代码有效,但我似乎无法使用深度冻结使我的测试正常工作。 I was trying to look at the redux example here http://redux.js.org/docs/basics/Reducers.html using .map to find the index with no luck.我试图在这里查看 redux 示例http://redux.js.org/docs/basics/Reducers.html使用.map来查找索引但没有运气。 Any ideas?有任何想法吗?

export default function myReducer(state = { toDisplay: [] }, action) {
  const { type, groupIndex, itemIndex } = action;
  const newObject = Object.assign({}, state);
  switch (type) {
    case actionTypes.TOGGLE_GROUP:
      newObject.toDisplay[groupIndex].isSelected = newObject.toDisplay[groupIndex].isSelected ? false : 'selected';
      return newObject;
    case actionTypes.TOGGLE_ITEM:
      newObject.toDisplay[groupIndex].values[itemIndex].isSelected = newObject.toDisplay[groupIndex].values[itemIndex].isSelected ? false : true;
      return newObject;
    default:
      return state;
  }
}

EDIT:编辑:

For anyone curious after watching a helpful redux video I came up with this:对于观看有用的redux 视频后好奇的人,我想出了这个:

export default function myReducer(state = { toDisplay: [] }, action) {
  const { type, groupIndex, itemIndex } = action;
  switch (type) {
    case actionTypes.TOGGLE_GROUP:
      return {
        ...state,
        toDisplay: [
          ...state.toDisplay.slice(0, groupIndex),
          {
            ...state.toDisplay[groupIndex],
            isSelected: state.toDisplay[groupIndex].isSelected ? false : 'selected'
          },
          ...state.toDisplay.slice(groupIndex + 1)
        ]
      };
    case actionTypes.TOGGLE_ITEM:
      return {
        ...state,
        toDisplay: [
          ...state.toDisplay.slice(0, groupIndex),
          {
            ...state.toDisplay[groupIndex],
            values: [
              ...state.toDisplay[groupIndex].values.slice(0, itemIndex),
              {
                ...state.toDisplay[groupIndex].values[itemIndex],
                isSelected: state.toDisplay[groupIndex].values[itemIndex].isSelected ? false : true
              },
              ...state.toDisplay[groupIndex].values.slice(itemIndex + 1)
            ]
          },
          ...state.toDisplay.slice(groupIndex + 1)
        ]
      };
    default:
      return state;
  }
}

Using a helper/library like suggested is probably the best route but my team wishes to not add another dependency.使用建议的助手/库可能是最好的方法,但我的团队不希望添加其他依赖项。

Firstly, Object.assign(...) only does a shallow copy.首先, Object.assign(...)只做一个浅拷贝。 See here .这里

As you have objects nested inside arrays nested inside objects I would highly recommend the immutability helpers from react (as mentioned by Rafael).由于您将对象嵌套在嵌套在对象内部的数组中,我强烈推荐 react 中的不变性助手(如 Rafael 所述)。 These allow you to do something like this:这些允许你做这样的事情:

case actionTypes.TOGGLE_GROUP:
  return update(state, {
    toDisplay: {
      [groupIndex]: {
        isSelected: {$set: newObject.toDisplay[groupIndex].isSelected ? false : 'selected'}
      }
    }
  });

If you are looking to modify a simple value inside an array with raw js then you can use something like this:如果您想使用原始 js 修改数组中的简单值,那么您可以使用以下内容:

return list
  .slice(0,index)
  .concat([list[index] + 1])
  .concat(list.slice(index + 1));

( source ) 来源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM