Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Local copy of React prop is read-only

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?

like image 818
Christopher Ronning Avatar asked Jan 11 '17 03:01

Christopher Ronning


People also ask

Are React props read only?

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.

Why are React props read only?

“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.

Is props are Uneditable?

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.

Can props be updated or read only?

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)


1 Answers

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.

like image 152
Special Character Avatar answered Sep 22 '22 01:09

Special Character