替换深子对象,同时在React中保持状态不可变

时间:2017-05-25 19:45:05

标签: javascript reactjs redux immutability

我是新的反应和减少。我有一个对象是一个子对象数组,其中包含数组

export function increaseSum(value, denom) {
    return { type: types.ADD_TO_SUM, value: value, denom: denom }
}

我有一个动作传递了一个值和面额的名称

function findDenomination(denoms, action) {
    let denomMap = {},
        currentDenom = {};
    for (let i = 0; denoms.length >= i + 1; i++) {
        let denomGroup = denoms[Object.keys(denoms)[i]];
        for (var key in denomGroup) {
            if (!currentDenom.length) {
                currentDenom = denomGroup[key].filter(x => x.name === action.denom);
                if (currentDenom.length > 0) {
                    denomMap.group = i;
                    denomMap.key = key;
                    denomMap.index = denomGroup[key].findIndex(x => x.name === action.denom);
                }
            }
        }
        if (currentDenom.length > 0) {
            break;
        }
    }
    return denomMap;
}

在我的reducer中,我写了一个帮助器类来识别这个面额在对象中的位置:

Object.assign

在reducer本身中,我使用function countableItems(state = initialState, action) { switch (action.type) { case types.ADD_TO_SUM: let denomMap = findDenomination(state.denomGroups, action); state.denomGroups = Object.assign({}, state.denomGroups, state.denomGroups[denomMap.group][denomMap.key][denomMap.index].sum = parseFloat(action.value)); return state; default: return state; } } 来制作denomGroups的深层副本,我想这会让它保持不变。

A state mutation was detected inside a dispatch

任何人都清楚为什么这会被标记为错误:import "github.com/Arachnid/solidity-stringutils/strings.sol"; contract Contract { using strings for *; // ... function smt() { var s = ""This-Is-A-Problem"".toSlice(); var delim = "-".toSlice(); var parts = new string[](s.count(delim)); for(uint i = 0; i < parts.length; i++) { parts[i] = s.split(delim).toString(); } } }

1 个答案:

答案 0 :(得分:1)

您试图改变不可变的。因此错误。

不可改变的全部意义在于,在创建之后,不可变的内容永远不会在其中的任何地方发生变化。这就是为什么所有改变它的函数都会创建一个不可变的新实例。如果你试图在一个不可变的内部改变某些东西,那仍然是一个突变,因而是坏的。

这确保您只需检查对象本身是否相等,而不必进行深入检查,以及确保数据完整性。

你应该做的只是改变它(如果你正在使用immutables库,你可以使用setIn),这将创建一个新的Map。您可以在state上调用它。

这样的事情:

case types.ADD_TO_SUM:
    const denomMap = findDenomination(state.denomGroups, action);
    return state.setIn(['denomGroup', denomGroup.key, denomGroup.index, sum], parseFloat(action.value));