【问题标题】:Updating an object within array in react redux reducer getting map() is not a function在react redux reducer中更新数组中的对象获取map()不是一个函数
【发布时间】:2018-01-11 10:25:35
【问题描述】:

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

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

调度一个动作后,我需要根据 ID 将该动作插入到其中一个 object[] 中。我目前正在使用以下脚本来更新减速器中的 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
        }
      ]
    }
  };

【问题讨论】:

  • 什么是数组[1]、数组[2]、数组[3]
  • 或者你的意思是说object2内的3个对象
  • @ShubhamKhatri 是的,我的错误。改变了上面的问题

标签: javascript reactjs redux react-redux


【解决方案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?

【讨论】:

  • 检查这个答案
  • 谢谢!使用 immutability-helper 代替,因为它提供了更好的性能。下面更新了代码。
  • 没问题。但是,它已经作为我在答案中添加的问题的答案存在
【解决方案2】:

'您可以查看库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 的所有功能。

【讨论】:

  • 这看起来很整洁!
  • 它是:-) 唯一的缺点是当您尝试将它与流或打字稿等类型系统一起使用时。你会立即失去类型......
【解决方案3】:

以下代码用于使用 immutability-helper 包。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 2020-10-08
    • 2018-09-06
    • 2020-01-04
    相关资源
    最近更新 更多