在react redux reducer中更新数组中的对象获取map()不是一个函数

时间:2017-08-03 17:07:32

标签: javascript reactjs redux react-redux

我有一个相当复杂/嵌套的redux商店,如下所示:

{
  object1
  {
    array:
    [
      object[1]: {
        id: 1,
        replace: ""
      }
      object[2]: {
        id: 2
        replace: ""
      }
      object[3]: {
        id: 3,
        replace: ""
      }
    ]
  }
}

在调度动作之后,我需要根据ID将动作插入到对象[]之一。我目前正在使用以下脚本来更新reducer中的 replace 。但是,由于 object2:{} 的大括号,这会将数组更改为对象。

case UPDATE:
  return {
    ...state,
    object1: {
      ...state.object1,
      array: {
        ...state.object1.array,
        [action.id]: {
          ...state.object1.array[action.id],
          replace: action.result
        }
      }
    }
  };

之后我的渲染会中断,因为在更改为对象后,object2.map不再是一个函数。如何在不将其转换为对象的情况下解决此问题?

以下将因语法错误而失败:

case UPDATE:
  return {
    ...state,
    object1: {
      ...state.object1,
      array: [
        ...state.object1.array,
        [action.id]: {
          ...state.object1.array[action.id],
          replace: action.result
        }
      ]
    }
  };

3 个答案:

答案 0 :(得分:1)

您无法使用扩展语法直接指定要修改的索引,您需要先找到索引并按照

进行操作
case UPDATE:
  var idx = state.object1.object2.findIndex(obj => obj.id === action.id)
  return {
    ...state,
    object1: {
      ...state.object1,
      object2: [
        ...state.object1.object2.slice(0, idx),
        {
            ...state.object1.object2[idx],
            replace: action.result 
        }
        ...state.object1.object2.slice(idx + 1)
      ]
    }
  };

否则你可以使用immutability-helper包。有关如何操作的示例,请参阅此答案

how to use Immutability helper to update a nested object within an array?

答案 1 :(得分:1)

'您可以查看库immutadot。它的目的是帮助以非常简洁的方式更新复杂的嵌套数据结构,并在创建时考虑到redux的使用。

在你的情况下,你可以这样写:

import { set } from 'immutadot'

...

  case UPDATE:
    return set(state, 'object1.arrary[' + id + '].replace', action.result)
    // or with templated string
    return set(state, `object1.arrary[${ id }].replace`, action.result)

...

它依赖于木材下的lodash,因此你可以使用lodash功能的所有功能。

答案 2 :(得分:0)

使用immutability-helper包的代码。

case UPDATE:
  return update(state, {
    object1: {
      array: {
        [action.id]: {
          replace: {
            $set: action.result
          },
        },
      },
    }
  });