简体   繁体   中英

Why is SetState in React updating other objects in handler?

In the onChange event handler, I am only making a setState() call on the userTxt but it looks like it also sets the state of the color object. Whats strange to me is that this is only happening to the color object but not to the age variable.

Was wondering if someone could please explain why this is happening? Here is a link to my webpackbin example. As you write in the input, the state is changed on the color object. .

I was hoping someone could please explain to me the mechanics of why this is happening. Thank you very much in advance.

import React, { Component } from 'react';

export default class Hello extends Component {

  constructor() {
    super();
    this.handleMe = this.handleMe.bind(this);
    this.state = {
        age: 21,
        colors: {
            best: 'blue',
            second: 'green'
        },
        userTxt: ""
    }
  }
  handleMe(e) {
        let myAge = this.state.age;
        let myColors = this.state.colors;

        myAge = myAge + 1;
        myColors['best'] = 'mistyrose';
        myColors['second'] = 'red';

        this.setState({ userTxt: e.target.value });
    }

  render() {
    const { age, colors, userTxt} = this.state;
    return (
      <div>
        <form action="">
          <input type="text"onChange={this.handleMe}/>
          <div>Age: {age}</div>
          <div>Colors - best: {colors.best}</div>
          <div>Colors - second: {colors.second}</div>
          <div>UserTxt: {userTxt}</div>
        </form>
      </div>
    )
  }
}[enter link description here][1]


  [1]: https://www.webpackbin.com/bins/-KvFx-s7PpQMxLH0kg7m

This is happening because you are directly manipulating the state here. myColors refers to the state's colors object.

  handleMe(e) {
        let myAge = this.state.age;
        let myColors = this.state.colors;

        myAge = myAge + 1;
        //directly mutating the state with these 2 lines.
        myColors['best'] = 'mistyrose';
        myColors['second'] = 'red';

        this.setState({ userTxt: e.target.value });
    }

You need to make a copy of this.state.colors like let myColors = Object.assign({}, this.state.colors)

The colors field in the state is an object which is stored as a reference. The age field is a integer and is stored as a primitive value.

When you assign the color field to myColors, both variables reference the same object. So when you update myColors, the colors field in the state gets updated.

When you assign the age field to myAge, it copies the value of the age field in state to the myAge field. So when you update myAge, it does not update the state.

More on this at Primitive value vs Reference value

To prevent this unintended side effect, you should create a new object and copy the values of colors from the state to it. You can do this by using

let myColors = {...this.state.colors};

when declaring the variable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM