2017-01-11 20 views
3

比方说,我有两个组件。父对象作为属性传递给对象,然后将其复制到本地数据存储中。它有一个功能来更新这个本地存储,它被传递给一个孩子。这里是我的父Component:React道具的本地副本是只读的

const Parent = ({stuff}) => { 
    const store = { 
    stuff: Object.assign({}, stuff); 
    } 

    const updateStuff = (thing, property) => store.stuff[thing].property = thing; 

    return <Child stuff={stuff} updateStuff={updateStuff} /> 
} 

子组件具有类似的结构 - 它使stuff副本,变异上<input>onChangestuff副本。然后它将自己的更新副本传递给它所收到的updateStuff函数,以便改变父项目的副本。这是孩子。

const Child = ({stuff, updateStuff}) => { 
    const stuff = { 
    thing1: Object.assign({}, stuff.thing1), 
    thing2: Object.assign({}, stuff.thing2) 
    } 

    const setProp = event => { 
    const update = event.target.value; 

    stuff.thing1.prop = update; 
    updateStuff(thing1, stuff.thing1.prop) 
    } 

    return (
    <div> 
     <input id="thing1" onChange={setProp} /> 
     <input id="thing1" onChange={setProp} /> 
    </div> 
) 
} 

注意,我用Object.assign基本上克隆stuff道具或其子属性,视情况必要。原因是这样的:一个React道具是只读的,因此我需要创建一个克隆来进行更改,然后再传递它以更改应用程序的状态(此处未显示)/

现在,子组件 - setProp突变stuff的正确属性,通过登录到控制台进行确认。然而,当方法得到updateTeam,我得到一个错误信息:Uncaught TypeError: Cannot assign to read only property 'side' of object '#<Object>'

然而,这两个组件使用相同的原则:我没有突变道具,而是我突变本地存储的道具克隆。为什么这对儿童有用,但对父母不起作用?

+1

这可能是Object.assign只做浅拷贝的结果。 [Object.asssign reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Deep_Clone)。你可以尝试在Object.assign()的任何地方深度克隆对象。类似于'newStuff:JSON.parse(JSON.stringify(stuff))'。我的想法是,对象的底层部分不是真正的副本。 –

+0

这实际上解决了这个问题。如果您将此格式设置为答案,我会很乐意接受它作为正确答案。 –

+1

所以我猜在我的父组件中'stuff'的属性实际上是对实际'stuff'属性的引用。这是一个正确的分析,@BrandonRoberts? –

回答

3

Object.assign只做道具Object.assign Reference的浅表副本。为了制作道具的真实深层副本(并排除错误),您可以使用newStuff: JSON.parse(JSON.stringify(stuff))进行深层复制。很高兴这有助于!

这背后的真正原因,给出一个例子:

let original = { 
    name: 'Test', 
    nestedObj: { 
     (...some properties) 
    } 
} 

在上面的例子中,原来的对象属性“名”是一个新的副本,但嵌套对象仍然是原来的一个参考。这种方式当你尝试编辑嵌套对象的部分时,它会引用原始对象,并大声说它是不可变的。

+0

非常感谢...我仍然不确定为什么Child没有发生同样的事情 - 考虑到我也在改变'thing'的属性(属性)。无论如何,谢谢。 –

+1

下面是深拷贝与浅拷贝的一个很好的答案:http://stackoverflow.com/questions/184710/what-is-the-difference-between-a-deep-copy-and-a-shallow-copy。当我遇到类似的问题时,这对我非常有帮助。 –

+1

您先生是高质量的用户。 –

-3

尝试改变constlet您的本地副本

+0

不是 - 'const thing'只意味着它不是一个变量,因此'thing'不能被重新分配 - 所以,如果我说'const thing = {prop:'value'}',我不能重新分配'thing',但我可以改变'thing.prop'的值。 –

+0

你是否正确地分配属性? 'store.stuff [thing] .property'应该是'store.stuff [thing] [property]'吗? – user3485959

+0

不是。这是React特有的问题。 –