如何在没有扩展运算符的情况下更改Redux状态的子片

时间:2017-05-06 20:26:29

标签: javascript redux

我需要更新状态切片的切片,而不更新整个切片;只有子切片。我已经看到其他人联合使用减速器来实现这一目标,但我还没有想出如何在我的项目中做到这一点。 Redux.js.org将此作为另一种方式来实现:

function updateVeryNestedField(state, action) {
    return {
        ....state,
        first : {
            ...state.first,
            second : {
                ...state.first.second,
                [action.someId] : {
                    ...state.first.second[action.someId],
                    fourth : action.someValue
                }
            }
        }
    }
}

不幸的是,我的项目是在javascript中。如何在没有扩展运算符的情况下使用vanilla javascript复制这个?我使用Object.assign尝试了一些变体,但无法使其发挥作用。

1 个答案:

答案 0 :(得分:1)

正如您所提到的,您可以使用Object.assign代替传播:

{...state, x: 1}

应该给你与

相同的结果
Object.assign({}, state, {x: 1})

请注意空对象作为Object.assign的第一个参数。这样做是将值从state复制到一个新的空对象,然后将值从{first: 1}复制到新对象中。

例如:

var a = { x: 1, y: 2}
var b = {...a, y: 3 }
console.log(a); // { x: 1, y: 2 }
console.log(b); // { x: 1, y: 3 }

相当于

var c = { x: 1, y: 2 }
var d = Object.assign({}, a, { y: 3 });
console.log(c); // { x: 1, y: 2 }
console.log(d); // { x: 1, y: 3 }

重要的是,ac都不变。 bdy提供了新值。

对于嵌套对象,请重复此过程:

function updateVeryNestedField(state, action) {
    return Object.assign({}, state, {
        first : Object.assign({}, state.first, {
            second : Object.assign({}, state.first.second, {
                [action.someId] : Object.assign({},
                    state.first.second[action.someId],
                    { fourth : action.someValue }
                )
            })
        })
    });
}

var oldState = { first: { second: { 'anId': { fourth: 3 } } } };
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 });
console.log(oldState.first.second.anId.fourth); // 3
console.log(newState.first.second.anId.fourth); // 5

但是,对于完整的ES2015支持,您也无法use computed keys。因此,您必须在return语句之前构建一些对象。例如:

function updateVeryNestedField(state, action) {
    // Create a temporary object to avoid use of computed keys
    var updatedSecond = Object.assign({}, state.first.second);
    updatedSecond[action.someId] = Object.assign({}, state.first.second[action.someId], {
        fourth: action.someValue
    });
    return Object.assign({}, state, {
        first : Object.assign({}, state.first, { second : updatedSecond })
    });
}

var oldState = { first: { second: { 'anId': { fourth: 3 } } } };
var newState = updateVeryNestedField(oldState, { someId: 'anId', someValue: 5 });
console.log(oldState.first.second.anId.fourth); // 3
console.log(newState.first.second.anId.fourth); // 5