Let's say I have two Components. The parent is passed an Object as a property, which it then copies into local data store. It has a function to update this local store, which gets passed down to a child. Here is my parent Component:
const Parent = ({stuff}) => {
const store = {
stuff: Object.assign({}, stuff);
}
const updateStuff = (thing, property) => store.stuff[thing].property = thing;
return <Child stuff={stuff} updateStuff={updateStuff} />
}
The Child Component has a similar structure -- it makes a copy of stuff
, and mutates its copy of stuff
on an <input>
's onChange
. It then passes its own updated copy of stuff to the updateStuff
function it received, in order to mutate the Parent's copy of the prop. Here is the Child.
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>
)
}
Notice, I've used Object.assign to basically clone the stuff
prop or its child properties, as the case necessitates. The reason for this: a React prop is read-only, and thus I need to create a clone to make changes on before passing it back to mutate the app's state (not shown here)/
Now, this works on the Child component -- setProp
mutates the correct property of stuff
, confirmed by logging to the console. However, when the method gets to updateTeam
, I get an error message : Uncaught TypeError: Cannot assign to read only property 'side' of object '#<Object>'
Yet, both Components use the same principle: I am not mutating the prop, but rather I am mutating a locally-stored clone of the prop. Why does this work for Child, but not for Parent?
When you use any React component you can pass it some input data that you want it to work with. These properties are called "props" and are read-only values that define the basic starting point for a component.
“Props” is a special keyword in React, which stands for properties and is being used for passing data from one component to another. Furthermore, props data is read-only, which means that data coming from the parent should not be changed by child components.
In ReactJS, the data can be passed from one component to another component using these props, similar to how the arguments are passed in a function. Inside the component, we can add the attributes called props; however, we cannot change or modify props inside the component as they are immutable.
Data from props is read-only, and cannot be modified by a component that is receiving it from outside. State data can be modified by its own component, but is private (cannot be accessed from outside) Props can only be passed from parent component to child (unidirectional flow)
Object.assign only does a shallow copy of the prop Object.assign Reference. In order to make a true deep copy of the prop (and get rid of the error) you can do a deep copy with newStuff: JSON.parse(JSON.stringify(stuff))
. Glad this helped!
The real reason behind this is given in an example:
let original = {
name: 'Test',
nestedObj: {
(...some properties)
}
}
In the example above, the original object property 'name' is a new copy but the nested object is still a reference to the original. This way when you try and edit the part of the nested object it references the original and yells that it is immutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With