逐点更新单个值,无需更改并重建对象的初始结构JS

问题描述 投票:0回答:1

我正在寻找一种更好地组织我的行动/减少者的方法,现在看起来像这样:

[SOME_ACTION]: state => ({
    ...state,
    isModified: true,
    orders: {
        ...state.orders
        // or maybe change something here
    },
    documentation: {
        ... state.documentation
       // or maybe change something here
    }
})

问题是该对象具有深层嵌套,我必须跟踪它的每个级别并将其相应地添加到任何地方。而且我必须编写所有这些内容以更新单个值。

我有什么选择?现在,我只希望能够通过指向要更改的内容来在嵌套的某个级别上更新一个/几个值。

javascript
1个回答
1
投票

您只需复制更改的对象及其父对象,而不是其子对象。例如,在您的示例中,我假设更改为isModified: true。您不需要复制ordersdocumentation,可以重复使用,因为它们没有更改:

[SOME_ACTION]: state => ({
    ...state,
    isModified: true
})

如果愿意,您可以给自己一个实用程序功能来进行更改。例如:

function newState(state, path, value) {
    const result = {...state};
    const lastKey = path[path.length - 1];
    let obj = state;
    for (const key of path.slice(0, path.length - 1)) {
        obj = obj[key];
    }
    obj[lastKey] = value;
    return result;
}

...或类似的东西(没有袖套)。

在那种特定情况下,由于变化很浅,所以并没有那么有用:

[SOME_ACTION]: state => newState(state, ["isModified"], true)

但是如果您进行了更改以使结构更深:

[SOME_ACTION]: state => newState(state, ["orders", someOrderId, "fulfilled"], true)

...写起来比等效的要少一些痛苦:

[SOME_ACTION]: state => ({
    ..state,
    orders: {
        ...state.orders,
        [someOrderId]: {
            ...state.orders[someOrderId],
            fulfilled: true
        }
    }
})

示例:

const state = {
    isModified: false,
    orders: {
        "order1": {
            customer: "Joe Bloggs",
            fulfilled: false
        },
        "order2": {
            customer: "Jane Doe",
            fulfilled: false
        }
    },
    documentation: {
        foo: {},
        bar: {}
    }
};

const someOrderId = Math.random() < 0.5 ? "order1" : "order2";
const updated = newState(state, ["orders", someOrderId, "fulfilled"], true);
console.log(`Updated order '${someOrderId}':`);
console.log(updated);

function newState(state, path, value) {
    const result = {...state};
    const lastKey = path[path.length - 1];
    let obj = state;
    for (const key of path.slice(0, path.length - 1)) {
        obj = obj[key];
    }
    obj[lastKey] = value;
    return result;
}
© www.soinside.com 2019 - 2024. All rights reserved.