Redux - Updating array values
If you are learning Redux, I'm positively sure that you will stumble upon this very common question:
So, before we dive into the possible solutions, let's recap these key concepts:
Related to array updates, there are two key points for avoiding mutations in Redux:
Remember:
Now, let's go:
Tip: In the above example, we are working on "newState" and "newCounter" arrays, both are copies of the current state when the reducer is invoked.
Tip: The "newInit" and "newMove" objects are copies of the current "game" state and they include all necessary arrays.
Here you have an excellent article: Immutable Update Patterns
What is the best way to change items of an array?
So, before we dive into the possible solutions, let's recap these key concepts:
- The state of the application lives as a single, immutable object within the store.
- Do not mutate the current state.
- Copy the current state and safely mutate the copy.
- The reducer returns the mutated copy as the next state.
Related to array updates, there are two key points for avoiding mutations in Redux:
- Using concat(), slice(), and …spread for arrays.
- Using Object.assign() and …spread for objects.
Remember:
The initial state object doesn’t change as well. The resulting state is a copy of the initial state.
Use Cases
These use cases are pretty straightforward and for both cases, these are the render and subscriber functions:
store.subscribe(render) ;
function render() {
const valueEl = document.getElementById('result');
valueEl.innerHTML = 'contador: ' + JSON.stringify(store.getState()) ;
}
Now, let's go:
Updating a plain Array
HTML markup
<div id="result"></div>
<p onclick="store.dispatch({ type: 'STATE_INIT' });">set initial state</p>
<p onclick="store.dispatch({ type: 'STATE_INC'});">increment [0] current state by 1</p>
<p onclick="store.dispatch({ type: 'STATE_PAYLOAD', position: 1 , value: 1 });">increment current state by a payloaded value</p>
Redux Reducer
function test( state = [], action) {
switch (action.type) {
case 'STATE_INIT':
console.log('STATE_INIT');
return [0,0,0,0] ;
case 'STATE_INC':
console.log('STATE_INC');
const newState = [...state] ;
newState[0] += 1 ;
return newState ;
case 'STATE_PAYLOAD':
console.log('STATE_PAYLOAD');
const newCounter = [ ...state ];
newCounter[action.position] = newCounter[action.position] += action.value ;
return newCounter ;
default:
return state ;
}
}
Tip: In the above example, we are working on "newState" and "newCounter" arrays, both are copies of the current state when the reducer is invoked.
Updating an Object
HTML markup
<div id="vresult"></div>
<p onclick="store.dispatch({ type: 'BOARD_INIT',board});">board initialization</p>
<p onclick="store.dispatch({ type: 'RECORD_MOVE', player: 'HUMAN', square: 7 });">HUMAN picked square #7</p>
<p onclick="store.dispatch({ type: 'RECORD_MOVE', player: 'COMPUTER', square: 2 });">COMPUTER picked square #2</p>
Vanilla JavaScript Code
let board = {
available: [0,1,2,3,4,5,6,7,8] ,
busy: [],
PC: [],
HUMAN: []
}
Redux Reducer
function game( state = [], action) {
switch (action.type) {
case 'BOARD_INIT':
const newInit = Object.assign({}, action);
return newInit ;
case 'RECORD_MOVE':
const newMove = Object.assign({}, state);
if(newMove.board.available.indexOf(action.square) > -1) { newMove.board.available.splice(action.square,1); }
if(newMove.board.busy.indexOf(action.square) < 0) { newMove.board.busy.push(action.square); }
if((action.player === 'HUMAN') && (!newMove.board.HUMAN.includes(action.square))) {newMove.board.HUMAN.push(action.square); }
if((action.player === 'COMPUTER') && (!newMove.board.PC.includes(action.square))) { newMove.board.PC.push(action.square); }
return newMove ;
default:
return state ;
}
}
Tip: The "newInit" and "newMove" objects are copies of the current "game" state and they include all necessary arrays.
Very Important
The Redux library won't stop you if you decide to mutate current states by yourself. It's up to you.Conclusion
There are other possibilities to achieve this goal, and also, be aware of common mistakes.Here you have an excellent article: Immutable Update Patterns
No comments