• Breaking News

    Redux - Updating array values

    If you are learning Redux, I'm positively sure that you will stumble upon this very common question:

    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:

    1. The state of the application lives as a single, immutable object within the store.
    2. Do not mutate the current state.
    3. Copy the current state and safely mutate the copy.
    4. 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