Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React state changes when its assigned variable changes

I am stuck with a strange issue with React.

this.state={
      testState: { testValue: "Test State" }
}
   
testFn = () => {
        let a;
        a = this.state.testState
        a.testValue = "Debugging is awesome";
        console.log(this.state.testState)
    }

If I have made any change in the assigned variable a, then it will reflect in the state also.

What I got in console is,

{testValue: "Debugging is awesome"}.

Any help will be appreciable

Edit: I don't want to change the state. I have to modify a without altering the state. How can I achieve this?

like image 253
Muhzin Avatar asked Mar 09 '20 08:03

Muhzin


People also ask

What happens when state changes in React?

React components has a built-in state object. The state object is where you store property values that belongs to the component. When the state object changes, the component re-renders.

How do I change my state value in React?

In controlled input element you store the value of input element in state and changes to that value is done by calling onChange method and then setting the state via this. setState({}) . Calling setState causes re-rendering to happen and dom gets the updated data based on new state.

What is Statein React?

What Is 'State' in ReactJS? The state is a built-in React object that is used to contain data or information about the component. A component's state can change over time; whenever it changes, the component re-renders.


7 Answers

The state changes because your variable a holds a reference to testState. This is a no-op. You should never change it directly and only use the setState function provided by react.

this.setState({ testState: { testValue: "Debugging is awesome" } });

If you don't want to change the state you can use the spread operator:

let a = { ...this.state.testState };
like image 190
Omar Avatar answered Oct 19 '22 22:10

Omar


Why does it act this way?

It's because objects and arrays in JavaScript are reference values. Wherever you update its value, it also updates the source. In this case, you'd want to make it immutable. You would do that by assigning a new object. In ES6 this can be done with the spread operator.

Solution

let a = { ...this.state.testState };

Further reading

  • Mozilla Web Docs: Spread syntax
like image 31
Shaun E. Tobias Avatar answered Oct 19 '22 22:10

Shaun E. Tobias


You have to deep copy the state if you don't want it to be effected (Object.assign):

this.state={
  testState: { testValue: "Test State" }
}

testFn = () => {
    let a;
    a = Object.assign({}, this.state.testState);
    a.testValue = "Debugging is awesome";
    console.log(this.state.testState)
}

Or you can use {...this.state.testState} instead of Object.assign

Note that using the spread operator {...} will not keep the prototype property (instanceof).

like image 36
Lev Buchel Avatar answered Oct 20 '22 00:10

Lev Buchel


You can use the spread operator to create a copy of an object

const newObj = {...obj};
like image 42
van Avatar answered Oct 19 '22 23:10

van


Using JS, when you affect an object to a variable (here, testState), it is passed by reference (See here for further explanation).

This means that if you modify the object through one of the variables, every variable referencing the source will have the change applied.

To solve your problem, you can use the spread operator, which copies the object without referencing it directly:

let a = {...this.state.testState}
like image 2
William A. Avatar answered Oct 20 '22 00:10

William A.


try:

this.state={
      testState: { testValue: "Test State" }
}

testFn = () => {
        const a = { ...this.state.testState };
        a.testValue = "Debugging is awesome";
        console.log(this.state.testState)
    }
like image 1
Andrei Cristea Avatar answered Oct 19 '22 23:10

Andrei Cristea


You have to use spread operator (...) for this instead of assigning directly.

this.state={
      testState: { testValue: "Test State" }
}
   
testFn = () => {
        let a;
        a = {...this.state.testState}
        a.testValue = "Debugging is awesome";
        console.log(this.state.testState)
    }
    
testFn()
like image 1
Mohit Prakash Avatar answered Oct 20 '22 00:10

Mohit Prakash