0

My react redux setup was working well until I needed to trigger a component update based on an update to a redux store variable. From research I feel that my issue is that I am not returning from my reducer in an immutable fashion such that an update is not triggered in the connected component after I dispatch an update to the redux store.

Action

import {GAMESETUP_IN, GAMESETUP_OUT} from "../api/strings";

export const gameSetupIn = ({gameType, gameRound, gameStocks, gameHistory} = {}) => ({
    type: GAMESETUP_IN,
    gameSetup: {
      gameType,
      gameRound,
      gameStocks,
      gameHistory
    }
});

export const gameSetupOut = () => ({
    type: GAMESETUP_OUT
});

Reducer

// default state
import {GAMESETUP_IN, GAMESETUP_OUT} from "../api/strings";

const gameSetupReducerDefaultState = {
    gameType: "",
    gameRound: "",
    gameStocks: [],
    gameHistory: []
};

// reducer which is a pure function
export default(state = gameSetupReducerDefaultState, action) => {
    switch (action.type) {
        case GAMESETUP_IN:
            // Return a new array
            return {
                ...state,
                gameType: action.gameSetup.gameType.toString(),
                gameRound: action.gameSetup.gameRound.toString(),
                gameStocks: action.gameSetup.gameStocks,
                gameHistory: action.gameSetup.gameHistory
            };
        case GAMESETUP_OUT:
            return {
                ...state,
                gameType: "",
                gameRound: "",
                gameStocks: [],
                gameHistory: []
            };
        default:
            return state;
    }
};

I feel like there are two very closely related questions. 1) How can I return immutable data from redux reducer? 2) Updating Redux state does not trigger componentWillReceiveProps

and also the base redux documentation 3) https://redux.js.org/basics/reducers/

I feel like the answer is right in front of me that I need to somehow use return Object.assign({}, state, { key: newValue }); during the return from redux. I am just looking for some help in modifying my reducer to ensure that it is immutable and thus will trigger a component update after a dispatch. Thank you.

1 Answer 1

1

This all looks non-mutating to me. Are you mutating any of the variables, e.g. gameHistory elsewhere? Your reducer should be the only function that does that.

You are giving the redux state a reference to the history, so if you append anything to that object elsewhere in code it could cause issues.

One solution, as you say, is to use gameHistory: Object.assign({}, action.gameSetup.gameHistory) to make a copy, but this will just be a "shallow" copy (if your object contains other objects, they will be copied by reference). The (disgusting hack, but as far as I know only way for general objects) of making a deep copy is to use deep_copy_obj = JSON.parse(JSON.stringify(my_obj)).

The immutable way of doing things is to have your reducer managing things like appending to history, and if you want to edit the history when a button is clicked, make the button dispatch an action.

Sign up to request clarification or add additional context in comments.

1 Comment

Just wanted to say thank you for the vote of confidence that I have it written in a non-mutating manner. I tried removing the state reference but that seemed to have no effect, I tried the shallow copy which actually re-cast the array to an object so that created more problems. I tried the deep copy hack, which actually produced that same behavior as the original code. Bottom line is you are correct and I think my problem must be elsewhere in the app. I think I have some suspect data flow where I copy data from this.props to this.state, basically re-copying redux data versus using it directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.