【问题标题】:Updating an inner element of object using Object.assign使用 Object.assign 更新对象的内部元素
【发布时间】:2016-12-27 23:02:00
【问题描述】:

在我的 redux reducer 中使用 Object.assign 更新对象的内部元素时,我需要一点帮助。

为了更好地解释这个场景,我使用的是 NBA 球队。我的 redux 商店中有一个 NBA 对象。我现在尝试仅更新特定团队的 teamMembers。我的 NBA 对象如下所示:

{
   teams: [
       {
          teamId: 123,
          teamName: "Los Angeles Lakers"
          teamMembers: [
             {id: "kbryant", fullName: "Kobe Bryant"},
             {id: "bingram", fullName: "Brandon Ingram"}
          ]
        },
        {
          teamId: 234,
          teamName: "Miami Heat"
          teamMembers: [
             {id: "cbosh", fullName: "Chris Bosh"},
             {id: "tjohnson", fullName: "Tyler Johnson"}
          ]
        }
   ]
}

我通过我的操作(即 action.teamId 和 action.members)将 teamId 和 members 传递给 reducer。

这是我目前所拥有的:

Object.assign({}, state, {
   nba: Object.assign({}, state.nba, {
      teams: Object.assign({}, state.nba.teams, {
         teamId[action.teamId] // I'm stuck here...
      })
   })
})

如何更新特定团队的 teamMembers?我知道我快到了,但需要一点帮助。谢谢。

【问题讨论】:

  • 不是重复的。该问题的建议也不适用。我只使用 Object.assign。
  • 您可以将相关的Object.assign 调用包装在IIFE 中并在其中做一些工作,包括任何数据突变。只需确保对Object.assign() 生成的新对象进行变异并return
  • 您是否尝试在teamMembers 中添加或删除对象?
  • @Sam 您正在尝试实现相同的目标,并且使用 immutability-helper 中的update 是一个有效的解决方案。

标签: javascript reactjs redux


【解决方案1】:

您可以使用动态索引属性扩展您拥有的代码,该属性旨在识别teams 数组中的哪个条目需要更新。 ES6 语法允许对象字面量中的动态属性,方法是将动态表达式包装在方括号中,如下所示:{ [index]: value },其中index 是变量或其他表达式。

这是最终的解决方案:

function getNewState(state, action) {
    var index = state.nba.teams.findIndex( t => t.teamId == action.teamId );
    if (index == -1) return state; // team not found
    return Object.assign({}, state, {
        nba: Object.assign({}, state.nba, {
            teams: Object.assign([], state.nba.teams, {
                [index]: Object.assign({}, state.nba.teams[index], { 
                    teamMembers: action.teamMembers 
                })
            })
        })
    });
}

var state = {
    nba: {
        teams: [{
            teamId: 123,
            teamName: "Los Angeles Lakers",
            teamMembers: [
                {id: "kbryant", fullName: "Kobe Bryant"},
                {id: "bingram", fullName: "Brandon Ingram"}
            ]
        }, {
            teamId: 234,
            teamName: "Miami Heat",
            teamMembers: [
                {id: "cbosh", fullName: "Chris Bosh"},
                {id: "tjohnson", fullName: "Tyler Johnson"}
            ]
        }]
    }
};

var action = { teamId: 123, teamMembers: [{id: "lnance", fullName: "Larry Nance"}] };
var newState = getNewState(state, action);
console.log(newState);
.as-console-wrapper { max-height: 100% !important; top: 0; }

请注意,使用像 Immutable 这样的库,这种操作会变得容易得多。

【讨论】:

  • 我认为这是一个很好的解决方案,即找出索引然后更新值。我仍然需要一段时间才能让它工作。在调试了一段时间试图弄清楚发生了什么之后,我在更新过程中意识到——因为我使用的是 Object.assign,所以我将 teamMembers 从一个数组转换为一个对象,这最终破坏了我的其余代码。因此,我没有使用 Object.assign 来创建 teamMembers 的新副本,而是使用了 slice,它运行良好。我将研究不可变库。谢谢。
  • 很高兴听到它成功了。我认为Object.assign 也应该可以工作,但是通过提供一个空数组作为第一个参数,以确保它始终是一个数组:Object.assign([], ...)。我刚刚更新了它。但是slice 当然也可以。
  • 我不知道我可以将 Object.assign 与空数组一起使用。刚刚又学到了一件事。你已经超级有帮助了。真的很感激!我会投票赞成你的答案。
猜你喜欢
  • 2016-12-01
  • 2018-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多