无法分配为只读属性

时间:2019-09-05 19:45:27

标签: javascript reactjs redux

我在理解为什么收到错误消息时遇到了一些麻烦:

  

TypeError:无法分配为只读对象“#”的属性“ description”

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

这是我的减速器:

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 个答案:

答案 0 :(得分: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
        }
    }

答案 1 :(得分:0)

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

#Quite a few libraries removed
import datetime, csv, os.path, datetime
#Setup Logging here
now=datetime.datetime.now()
logfilename='FBlog_' + str(now.strftime('%Y-%m-%d_%H-%M-%S'))
#print(logfilename) \#removed as part of removing any console visibility
logfb=open('logs/%s.txt' % logfilename, 'w+')
startstring='Starting run ' + str(now.strftime('%Y-%m-%d_%H:%M:%S')) + '\n'
logfb.write(str(startstring))
logfb.close()

##########Application build code for pyinstaller:############
import PyInstaller.__main__
PyInstaller.__main__.run([
    '--name=%s' % 'TestApp',
    '--onefile',
    '--noconsole',
    '--clean',
    'TestApp.py'
])

希望这会有所帮助!

相关问题