What happens when directly assign a new object to `this.state` in React? [closed]

  javascript, react-dom, reactjs

First, I know that it is an anti-pattern in React to directly mutate properties of this.state, and one should use this.setState().

I am just curious about what will happen if I directly assign a new object to this.state and use this.forceUpdate() to re-render.

Here is my code:

let foo, bar;
class Counter extends React.Component {
  constructor() {
    super();
    foo = this.state = {
      cnt: 0,
    };
  }

  increase = () => {
    console.log('before: ', this.state);  // before:  {cnt: 0}
    // debugger
    bar = this.state = { cnt: this.state.cnt + 1 };
    // debugger
    console.log('after: ', this.state);   // after:  {cnt: 1}
    this.forceUpdate();
  };

  decrease = () => {
    this.state.cnt--;
    this.forceUpdate();
  };

  render() {
    console.log('render: ', this.state);  // render:  {cnt: 0}
    console.log(foo === this.state);  // true
    console.log(bar === this.state);  // false
    // debugger
    return (
      <div>
        <button onClick={this.decrease}>-</button>
        <span style={{ margin: '20px' }}>{this.state.cnt}</span>
        <button onClick={this.increase}>+</button>
      </div>
    );
  }
}

ReactDOM.render(<Counter />, document.getElementById('root'));
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>

…and this is my result:

before assignment

after assignment

in render

As you can see, the assignment did happen, but in render() it is invalid, this.state is back to the initial value in constructor()!

More interesting thing is, the ‘anti-pattern’ one, decrease() in my code, seems to work well.

So besides what happened after the assignment, I also want to know why the assignment gets ignored silently.

I’m using [email protected], here are my script tags:

  <script src="https://unpkg.com/[email protected]/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/[email protected]/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

Source: Ask Javascript Questions

LEAVE A COMMENT