0
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 1
    }
  }
  componentDidMount() {
    this.setState({
      num: this.state.num+1
    });
    this.setState({
      num: this.state.num+1
    });
  }
  render() {
    return (
      <div>
        { this.state.num }
      </div>

    )
  }
}

Calling setState twice in componentDidMount uses +1 to update num, but finally num is 2

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      num: 1
    }
  }
  componentDidMount() {
    this.setState({
      num: ++this.state.num
    });
    this.setState({
      num: ++this.state.num
    });
  }
  render() {
    return (
      <div>
        { this.state.num }
      </div>

    )
  }
}

setState updates num using auto increment, but finally num is 3。

What is the difference between the two methods? And how to understand how setState updates the state?

thank you

heyden
  • 179
  • 1
  • 9
  • 2
    Read [Why avoid increment (“++”) and decrement (“--”) operators in JavaScript?](https://stackoverflow.com/q/971312/215552) and its answers as to why using `++` like that is a bad idea in general (or not, depending on the answers you read). – Heretic Monkey Nov 26 '18 at 15:17
  • For how React uses `setState`, the [documentation does a pretty good job](https://reactjs.org/docs/state-and-lifecycle.html) – Heretic Monkey Nov 26 '18 at 15:18
  • 1
    You are mixing two questions as one. I've closed this as a *duplicate* because the main question here is the use of `setState` and the other, more "minor" question is related the *JS* basics and @HereticMonkey addressed it here in the first comment. – vsync Nov 26 '18 at 15:33

2 Answers2

2

setState is asynchronous, after it returns this.state hasn't changed yet:

this.setState({
  num: this.state.num+1 // this.state.num is 1, so the value here is 2
});
this.setState({
  num: this.state.num+1 // this.state.num is still 1, so the value is still 2
});

So that's the same as

this.setState({
  num: 2
});
this.setState({
  num: 2
});

With your second example however, you're mutating this.state.num so

this.setState({
  num: ++this.state.num // this.state.num is 2 after increment
});
this.setState({
  num: ++this.state.num // this.state.num is 3 after incrementing again
});

And this is effectively the same as

this.setState({
  num: 2
});
this.setState({
  num: 3
});

In general it is not a good idea to call setState and compute a new value based on this.state. If you want to change the state based on the current value in state, don't access this.state! Instead, give a callback to setState:

setState(state => ({ num: state.num + 1 })

Consider this example from the ReactJS docs:

For example, if you attempt to increment an item quantity more than once in the same cycle, that will result in the equivalent of:

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)

Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form, instead:

this.setState((state) => {
  return {quantity: state.quantity + 1};
});
Stefan
  • 675
  • 3
  • 9
1

setState is asynchronous, so you can't depend on the current state while updating it they way you are. please refer to this documentation, especially the part where a similar example is discussed :

This form of setState() is also asynchronous, and multiple calls during the same cycle may be batched together. For example, if you attempt to increment an item quantity more than once in the same cycle, that will result in the equivalent of: ...etc

Fawzi
  • 359
  • 2
  • 12