我如何正确地从React Redux Reducer返回不可变数据

时间:2019-12-30 20:16:22

标签: javascript reactjs redux react-redux

我的React Redux设置运行良好,直到需要基于对Redux存储变量的更新来触发组件更新。从研究中,我觉得我的问题是我不是以不变的方式从我的reducer返回的,这样在将更新分派到redux存储后,不会在连接的组件中触发更新。

操作

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
});

减速器

// 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;
    }
};

我觉得有两个密切相关的问题。 1)How can I return immutable data from redux reducer? 2)Updating Redux state does not trigger componentWillReceiveProps

以及基本的redux文档 3)https://redux.js.org/basics/reducers/

我觉得答案就在我眼前,我需要在redux返回期间以某种方式使用return Object.assign({}, state, { key: newValue });。我只是在寻求一些有关修改我的reducer的帮助,以确保它是不可变的,因此将在分派后触发组件更新。谢谢。

1 个答案:

答案 0 :(得分:1)

这一切对我来说似乎都是不变的。您是否正在突变任何变量,例如gameHistory在其他地方?减速器应该是执行此操作的唯一功能。

您正在为redux state提供历史记录的引用,因此,如果在代码中的其他位置向该对象附加任何内容,则可能会导致问题。

一个解决方案,如您所说,是使用gameHistory: Object.assign({}, action.gameSetup.gameHistory)进行复制,但这只是一个“浅”副本(如果您的对象包含其他对象,则将通过引用复制它们)。进行深拷贝的(令人作呕的hack,但据我所知,这仅是通用对象的唯一方法)是使用deep_copy_obj = JSON.parse(JSON.stringify(my_obj))

做事的一成不变的方法是让减速器管理诸如追加到历史记录之类的事情,如果您想在单击按钮时编辑历史记录,请使该按钮调度一个动作。