React – prevState

By | 16/06/2020

In this post, we will see what prevState is and how to use it.
From React docs:
“React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument”

We create a component called ClickCounter:

[CLICKCOUNTER.JS]

import React, { Component } from 'react'

class ClickCounter extends Component {
    constructor() {
        super();
        this.state = {
          count: 0
        };
      }

      Add()
      {
          this.setState({
              count : this.state.count +1
          })
      }

    render() {
        return (
            <div>
                <div>
                    Total Click: {this.state.count}
                </div>
                <div>
                    <button onClick={() => this.Add()}>Add</button>
                </div>
            </div>
        )
    }
}

export default ClickCounter



Then, we add it into App.js and we run the application:

[APP.JS]

import React from 'react';
import './App.css';
import ClickCounter from './components/ClickCounter';


function App() {
  return (
    <div className="App">
      <header className="App-header">
        <ClickCounter></ClickCounter>
      </header>
    </div>
  );
}

export default App;



Now, we add a method called Ten into ClickCounter and then we run the application:

import React, { Component } from 'react'

class ClickCounter extends Component {
    constructor() {
        super();
        this.state = {
          count: 0
        };
      }

      Add()
      {
          this.setState({
              count : this.state.count +1
          })
      }

      Ten()
      {
        var i;
        for (i = 0; i < 10; i++) {
            this.Add()
        }
      }

    render() {
        return (
            <div>
                <div>
                    Total Click: {this.state.count}
                </div>
                <div>
                    <button onClick={() => this.Ten()}>Add</button>
                </div>
            </div>
        )
    }
}

export default ClickCounter



We can see that the new method doesn’t work in fact, the correct output had to be 10 at the first click, 20 at the second click and so on.
But, why doesn’t it work?
It doesn’t work because, React makes group multiple setState calls in to a single update for better performance.
In order to fix it, we have to use “a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument

We modify the component ClickCounter:

[CLICKCOUNTER.JS]

import React, { Component } from 'react'

class ClickCounter extends Component {
    constructor() {
        super();
        this.state = {
          count: 0
        };
      }

      Add()
      {
          this.setState((prevState, props) => ({
              // in this case, we don't need to use props
              count : prevState.count + 1
          }))
      }

      Ten()
      {
        var i;
        for (i = 0; i < 10; i++) {
            this.Add()
        }
      }

    render() {
        return (
            <div>
                <div>
                    Total Click: {this.state.count}
                </div>
                <div>
                    <button onClick={() => this.Ten()}>Add</button>
                </div>
            </div>
        )
    }
}

export default ClickCounter



Now, if we run the application, this will be the result:



Leave a Reply

Your email address will not be published. Required fields are marked *