开发者问题收集

无法分配给只读属性

2019-09-05
33275

我不明白为什么我会收到错误消息:

TypeError: Cannot assign to read only property 'description' of object '#'

我知道原理是我不想修改 Reducer 中的状态。相反,我想返回状态的新副本。

这是我的 Reducer:

action TOGGLE_CHECKBOX:
    {
        let copyOfItems = [...state.items]; // create a new array of items

        copyOfItems.forEach(i => i.description = "newDescription");

        // return a new copy of the state
        return {
            ...state,
            items: copyOfItems
        }
    }

这是我的 Reducer 测试:

it ('Test that each item description is set', () => {
    const state = {
        items: [
            { description: "d1" },
            { description: "d2" }
        ]
    }

    deepFreeze(state);

    expect(MyReducer(state, { type: TOGGLE_CHECKBOX })).toEqual({
        items: [
            { description: "newDescription" },
            { description: "newDescription" }
        ]
    });
});

但是,我收到了上述错误消息。如果我删除 deepFreeze ,测试就会通过。这意味着我以某种方式修改了原始状态,但我无法弄清楚为什么,特别是因为我创建了一个新的扩展项目数组。

任何帮助都将不胜感激。

2个回答

数组展开运算符对 state.items 数组进行浅拷贝,但不会复制该数组内的对象。为了获取包含已修改项目的新数组,您可以映射 state.items 并使用对象展开运算符来更新项目:

action TOGGLE_CHECKBOX:
    {
        const copyOfItems = state.items.map(
          i => ({...i, description: 'newDescription'})
        ); // create a new array of items with updated descriptions

        // return a new copy of the state
        return {
            ...state,
            items: copyOfItems
        }
    }
azundo
2019-09-05

扩展运算符对数组进行浅拷贝,这意味着数组内的对象仍将保留对原始值的引用。您需要为每个对象创建一个新副本,然后像这样更新每个对象的描述

let copyOfItems = state.items.map( obj => ({
  ...obj,
  description: "newDescription"
})); 

return {
  ...state,
  items: copyOfItems
}

希望这有帮助!

Hemant Parashar
2019-09-05