50

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/

Seth
  • 10,198
  • 10
  • 45
  • 68
Aminadav Glickshtein
  • 23,232
  • 12
  • 77
  • 117

9 Answers9

97

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

Athena
  • 3,200
  • 3
  • 27
  • 35
William Choy
  • 1,291
  • 9
  • 7
  • 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 ? – Pravin Poudel Aug 09 '19 at 15:55
  • @pravinpoudel take look at my answer at https://stackoverflow.com/a/61275983/1706351 . I designed an example to show an error caused by the wrong usage – Onilton Maciel Apr 17 '20 at 16:13
  • this.setState((prevState, props) => ({ counter: prevState.counter + 1 })); 100% working – GUGAN RAJ Jan 28 '22 at 08: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 })
Anthony Dugois
  • 2,042
  • 13
  • 17
  • 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 Sep 15 '17 at 01: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. May 28 '18 at 09: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.

Igorsvee
  • 4,101
  • 1
  • 25
  • 21
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  
Sandeep Ranjan
  • 824
  • 15
  • 33
1

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;
isherwood
  • 58,414
  • 16
  • 114
  • 157
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()} >
Hitesh Subnani
  • 589
  • 8
  • 11
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;

Mohammd Omar
  • 31
  • 1
  • 8
Mr.Sabin
  • 19
  • 1
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

Bao Huynh Lam
  • 974
  • 4
  • 12
-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.

Aminadav Glickshtein
  • 23,232
  • 12
  • 77
  • 117
  • 5
    You should have a look at [Anthony's Answer](http://stackoverflow.com/a/39316556/3715818). You should never mutate your state directly and therefore all ++-operators shall be avoided. – rzueger Sep 04 '16 at 13:38