52

Why when I am doing this.setState({count:this.state.count*2}) it is working, but when I am doing: this.setState({count:this.state.count++}) it is not working?

Why, and how to fix it?

Full code:

var Hello = React.createClass({
    getInitialState:function(){
    return {count:parseInt(this.props.count)}
  },
    a:function(){
    this.setState({count:this.state.count++})
    console.log(this.state)
  },
  render: function() {
    console.log(this.state)
    return <div onClick={this.a}>Click to increment the counter<b> {this.state.count} </b></div>;
  }
});

ReactDOM.render(
  <Hello count="1" />,
  document.getElementById('container')
);

But this code is working:

a:function(){
    this.setState({count:this.state.count*2})
    console.log(this.state)
  },

JSFiddle: https://jsfiddle.net/69z2wepo/55100/

9 Answers 9

99

setState is an async function. React may batch a bunch of setStates together. So the value of this.state.count is the value at the time you make the request.

A better solutions to call a function that gets evaluated at the time the setState gets executed.

this.setState((prevState, props) => ({
    counter: prevState.counter + 1
})); 

from https://facebook.github.io/react/docs/state-and-lifecycle.html

3
  • i have read through documentation too but couldnot understand on why previos state should be used on using state data . Can u please tell me why is this.state.count is the value at the time you make request ? Commented Aug 9, 2019 at 15:55
  • @pravinpoudel take look at my answer at stackoverflow.com/a/61275983/1706351 . I designed an example to show an error caused by the wrong usage Commented Apr 17, 2020 at 16:13
  • this.setState((prevState, props) => ({ counter: prevState.counter + 1 })); 100% working
    – GUGAN RAJ
    Commented Jan 28, 2022 at 8:36
82

By doing this.state.count++, you mutate the state, because it's the same thing than doing this.state.count += 1. You should never mutate the state (see https://facebook.github.io/react/docs/component-api.html). Prefer to do that instead:

this.setState({ count: this.state.count + 1 })
2
  • 1
    yeah, subtle, but makes sense. The incremental operator (++) works directly against the state value, so yeah, shouldn't be allowed. But not obvious. Thanks!
    – Maniaque
    Commented Sep 15, 2017 at 1:42
  • 7
    Please consider looking at @William Choy's answer. This is the recommended way to increment the state from official React documentation.
    – Arsen K.
    Commented May 28, 2018 at 9:36
3

The setState function returns before this.state.count is incremented because you are using a post-fix operator (++). Also, setState is asynchronous, it accepts a callback as the second argument which get triggered when the state has been updated, so you should put your console.log inside of the cb.

2

You are trying to mutate state (access this.state.field and increase its value) that's what ++ is. It tries to increase that state value, and then assign it to new state :) Only ever mutate state by calling setState. Try

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

or

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

// new state variable inside function's scope, we can play with that, ++ even safely. but don't call ++ on this.state ever. In general, don't use ++, it's bad practice.
For simple assignments

a+=1 || a-=1 || a*=1 || a%=1  

are better, or even write them explicitly.

 a = a + 1  
2

We can use the above snippet for counter increment, decrement and reset when an event occurs.

import { useState } from "react";
const Count = () => {
    const [num, setNum] = useState(0);

    const CounterI = () => {
       setNum (num+1);   
    }
    const CounterD = () => {
        setNum (num-1);
    }
    const ResetCounter = () =>{
        setNum (0);
    }
    return(
        <div>
            <p>Count Value: {num}</p>
            <button onClick={CounterI}>Counter Increment</button>
            <button onClick={CounterD}>Counter Decrement</button>
            <button onClick ={ResetCounter} >Reset</button>
        </div>
    );
}

export default Count;
0
0

You can bind that using bind(this) function eg:-

<div onClick={this.increase.bind(this)}>

or you can use Arrow function that will bind for you eg:-

<div onClick={()=> this.increase()} >
0

Another reason is because "something++" does MUTATE the value, but return the OLD VALUE. "++something" also MUTATE +1 the same way, but return the NEW VALUE

a = 3
console.log(a++) // Will log out the OLD VALUE 3, but in memory `a` will be mutated into 4
console.log(a++) // Will log out OLD VALUE 4, but in memory `a` will be mutated into 5
console.log(++a) // Will log out 6, since 5+1=6 is the new value

But all in all, do not mutate states in React

0

hope this helps for you

import { render } from '@testing-library/react';
import React, { Component } from 'react';


class Counter extends Component{
    state = {
        count: 0,  
    };
    handleIncrement = () => {
        this.setState({ count: this.state.count + 1 })
    };
    handleDecrement = () => {
        this.setState({ count: this.state.count - 1 })
    };

    render(){
        return(
            <div>   
                <button onClick={this.handleIncrement} className="btn btn-secondary btn-sm m-4 ">Increment</button>
                <span className = "badge bg-primary m-5">{this.state.count}</span>
                <button onClick={this.handleDecrement} className="btn btn-secondary btn-sm ">Decrement</button>
            </div>
        )
    }
};

export default Counter;

2
  • 1
    After more than 4 years of an accepted answer, a post should add new information or additional value.
    – Richard
    Commented Aug 24, 2021 at 6:06
  • Some explanation would make this answer better. See How to Answer.
    – isherwood
    Commented Aug 1, 2022 at 19:04
-1

I found an solution. When I am doing this.setState({count:++this.state.count}) it is working.

The reason is when I am doing this.setState({count:this.state.count++}) the new state.count value not being sent to the setState React function.

1
  • 5
    You should have a look at Anthony's Answer. You should never mutate your state directly and therefore all ++-operators shall be avoided.
    – rzueger
    Commented Sep 4, 2016 at 13:38

Not the answer you're looking for? Browse other questions tagged or ask your own question.