Home > Software design >  setState mutates the object reference
setState mutates the object reference

Time:12-01

I am getting an object from parent component and setting to state. In child component I am updating the state, but the parent reference object values also changing instead of only state changes.

Parent Component has a huge object,

obj = {
 values: {
   per1: { name: "rsk" },
   per2: { name: "ssk" },
 }
}

Child Component:

const ChildComponent = ({obj}) => {
  const [inp, setInp] = useState(obj.values);

  const onChange = useCallback(({target}) => {
   setInp((prev) => {
     const nD = { ...prev };
     //k1, k2 comes from some logic
     nD[k1][k2] = target.value; 
     return nD;
   })
  }, []);

  return (
    Here the "inp" state is looped by objects and keys in text box to build a html form
  )
}

Here the question is, why the core obj.values also changing on onChange setInp time. I dont want to disturb the obj.values untill i submit the form. Because before submit the Form, I need to validate,

obj.values are equal or not to inp state values

Any idea on this.

CodePudding user response:

The original object is changing because in JS, when you pass an array or an object in such a way, you are actually passing a reference to the original object/array.
Meaning that any changes made to the reference, will also affect the original.

In-order to avoid using the reference, you can copy the object/array and work with the copy instead.

There are a few ways of doing this, the simplest IMO is using the spread syntax.

Example:

const ChildComponent = ({obj}) => {
  const [inp, setInp] = useState({...obj.values});
  ...
}

What we do here is "spread" the contents of obj.values into a new object, thus creating a new object and avoiding using the reference.

Note that the spread syntax only makes a shallow-copy, this isn't necessarily an issue unless you have some complex object which contains some other nested objects within it.
If you do need to perform a deep-copy, one simple way of doing it is via JSON methods.

Example:

const clone = JSON.parse(JSON.stringify(original));

CodePudding user response:

First, this obj variable is incorrect because per1 is defined as object and object consist of key and value, but it is like a string array so please check that, and below is solution

In Child Component you should create a copy of that obj variable

  const [inp, setInp] = useState(Object.assign({}, obj.values));

Bz if you set inp as the same variable it will pass the address of that variable so for that you need to create the copy and then you can change that inp.

  • Related