Redux:清除数组对象的另一种方法

时间:2020-06-01 20:46:28

标签: javascript redux

我的状态可能看起来像这样:

 [
  0: {
    "id": "8e9x23x2wto",
    "name": "test-player",
    "currentFrame": 1,
    "rolls": {
      "1": [1,3],
      "2": [1,6],
      "3": [1,6],
      "4": [3,8],
      "5": [4,5],
      "6": [7,6],
      "7": [8,1],
      "8": [5,2],
      "9": [2,1],
      "10": [1,1]
    },
    "totalWins": 0
  }
]

我正在清除rolls对象并像这样重置currentFrame

case RESET_GAME:
  return {
    ...state,
    players: state.players.map((player) => {
      return {
        ...player,
        currentFrame: 1,
        rolls: Object.assign(player.rolls, Object.values(player.rolls).map(() => []))
      }
    }),
  } 

但是,有时rolls中的随机数组不会被清除-可能是第二个,可能是最后一个...我不知道如何。

是否有其他方法可以清除rolls,使其仅由空数组组成,或者有人对为什么会发生这种情况有解释? 任何输入都非常感谢!

3 个答案:

答案 0 :(得分:2)

我不确定100%,但是从这个角度看,我敢打赌这些问题是由于player.rolls对象的突变而不是创建它的干净版本而引起的。

现在,带有对象的代码正在创建一个新对象,并用旧对象中的键/值填充该新对象。这样可以保持对象的不变性,而不是使原始对象变异。 React / Redux往往对可变对象不好。

一般示例

可变示例:

const x = {};
Object.assign(x, {'a': 1, 'b': 2});
// x is now {'a': 1, 'b': 2}

在此示例中,我们采用x并将其变异。请注意,这里我们也将const与x一起使用有点棘手,这仅意味着我们无法重新分配x所代表的“指针”,但仍可以更改该指针所指向的值。这么说

const x = {};
x = 2; // Will not work

不可变的示例:

var x = {};
x = {...x, ...{'a': 1, 'b': 2}}; // assign x to a new object populated by the previous x and the new stuff

在这种情况下,我们没有突变x对象,而是将x分配给了一个新对象,该对象使用旧x对象中的键/值和我们想在其中包含的新对象键/值来填充(但在这种情况下,则不必要,因为x最初没有任何键/值。

您的代码

return { // not mutating
    ...state,
    players: state.players.map((player) => { // not mutating
      return { // not mutating
        ...player,
        currentFrame: 1,
        rolls: Object.assign( // mutating player.rolls rather than making a new rolls object.
          player.rolls, 
          Object.values(player.rolls).map(() => [])
        ) 
      }
    }),
  }

我建议您做类似...

return {
    ...state,
    players: state.players.map((player) => {
      return {
        ...player,
        currentFrame: 1,
        rolls: []
      }
    }),
  }

这更简单,更干净,而且正如您所说,您只是清除了整个rolls键...除非我误解了?

另请参阅Object.assign's MDN page,其中指出 目标对象-应用于源属性的对象,在修改后会返回 (以粗体显示)。

我想不出很多情况,您想使用Object.assign来使用散布运算符({...{'a': 1}, ...{'b': 2}})。

编辑

再来看一遍,我意识到您想重新制作rolls对象中的10个条目,而不是完全丢失它们。

我认为更好的解决方案是只制作一个包含空条目的新鲜对象。即

return {
    ...state,
    players: state.players.map((player) => {
      return {
        ...player,
        currentFrame: 1,
        rolls: {
           "1": [0,0],
           "2": [0,0],
           "3": [0,0],
           "4": [0,0],
           "5": [0,0],
           "6": [0,0],
           "7": [0,0],
           "8": [0,0],
           "9": [0,0],
           "10": [0,0]
        }
      }
    }),
  }

我不确定为什么要在列表上使用带有数字键的对象,但是可以。

答案 1 :(得分:2)

常见的是:

  1. const initialState = {...}
  2. 将其用作商店createStore(myReducer, initialState)的初始状态
  3. 并将其用于您的重置操作case RESET_GAME: return initialState

答案 2 :(得分:1)

您可以使用Object.fromEntries

players: state.players.map((player) => {
      return {
        ...player,
        currentFrame: 1,
        rolls: Object.fromEntries( Object.keys(player.rolls).map((key)=>[key,[]]))
      }
    }

let player = {
  rolls: {
    "1": [1, 3],
    "2": [1, 6],
    "3": [1, 6],
    "4": [3, 8],
    "5": [4, 5],
    "6": [7, 6],
    "7": [8, 1],
    "8": [5, 2],
    "9": [2, 1],
    "10": [1, 1]
  }
}
console.log(Object.fromEntries( Object.keys(player.rolls).map((key)=>[key,[]])))

相关问题