My reducer looks like this:
const players = (state = {}, action) => {
switch (action.type) {
case 'UPDATE_PLAYERS_CARDS':
return Object.assign({}, state, {
[action.player]: {
name: state[action.player].name,
score: state[action.player].score,
cards: action.cards
}
})
default:
return state
}
}
export default players
Basically, I just want to update the players cards but if I don't include the name and the score, then those get deleted in the new state.
Ideally I need to just do something like this: state[action.player].cards = action.cards
but one of the rules is to never mutate the state.
The method above will work, but that requires me to always know the data structure so if I add something else to it in the future, I would need to remember to come back to this reducer and add that back in so I don't lose it.
Is there a better way to accomplish this?
Edit: Thanks to Vijay for the suggestion for multiple object assigns. I ended up getting it to work with this:
case 'UPDATE_PLAYERS_CARDS':
const playerObject = Object.assign(state[action.player], { cards: action.cards });
return Object.assign({}, state, {
[action.player]: playerObject
});
How is that? Let me know if there are any improvements I can make.
Multiple Object.assign
methods look ugly.
You can do:
return { ...state.action.player, cards: action.cards }
Note: You'll need stage-2
babel preset to use this.
Once the data structure to update becomes fairly complex, you can use ImmutableJS 's setIn
, updateIn
methods to do deep updates easily.