【问题标题】:Cannot assign to read only property无法分配给只读属性
【发布时间】:2019-09-05 19:45:27
【问题描述】:

我无法理解为什么会收到错误消息:

TypeError:无法分配给对象“#”的只读属性“描述”

我知道原则是我不想修改我的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 测试通过。这意味着我以某种方式修改了原始状态,但我不知道为什么,尤其是因为我创建了一个新的展开项目数组。

任何帮助将不胜感激。

【问题讨论】:

标签: javascript reactjs redux


【解决方案1】:

数组扩展运算符制作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
        }
    }

【讨论】:

    【解决方案2】:

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

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

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2019-05-08
      • 2019-12-06
      • 2020-02-17
      • 2014-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多