Cognnox HR
Cognnox HR

Reputation: 11

Why this event handling function is being called twice and updates the state twice in react?

import React, { Component } from 'react'
 
class TestState extends Component{ 

    constructor(props){
        super(props)
        this.state = {
            count:1
        }
        this.handleClick = this.handleClick.bind(this)
    }
    handleClick(){
        console.log(this.state)
        this.setState (state=>{
          return  state.count++
        })
    }
    render(){
        return <div>
            <button onClick={this.handleClick} >Click</button>
            {this.state.count}
        </div>
    }
}
export default TestState

In the above code, when I click the button the counter increases by double value every time I click it .. e.g. On clicking the button the count will increase by 1, 3, 5, 7? But state.count should only increase once because of the ++ operator.

Upvotes: 1

Views: 278

Answers (3)

codemonkey
codemonkey

Reputation: 7915

Mutating state directly, as you do in your example, can lead to odd behavior and is never advisable. Here is a quote from the React docs:

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

By doing this state.count++ you throw React for a loop and as such see unexpected results.

I would rewrite your code like this: (https://codesandbox.io/s/red-lake-yk9gy?file=/src/App.js):

import React, { Component } from "react";

class TestState extends Component {
  constructor(props) {
    super(props);
    this.state = { count: 1 };
  }
  handleClick = count => {
    count++;
    this.setState({count});
  };
  render() {
    const { count } = this.state;
    return (
      <div>
        <button onClick={() => this.handleClick(count)}>Click</button>
        {count}
      </div>
    );
  }
}

export default TestState;

Upvotes: 0

Dan der Mensch
Dan der Mensch

Reputation: 332

The first answer is a solution, but the lifecycle method can be executed another way:

In my experience, ES6 fashion lends a DRY approach to updating state. Use of anonymous functions and implicit returns allow omission of the return keyword even though they aren't required if you don't rely on the value for another calculation ( Not recommended due to #setState's async nature ).

handleClick() {
    console.log( this.state )
    this.setState( state => ({
      counter: state.count + 1
    }))
    
}

For more on the matter see: https://reactjs.org/docs/state-and-lifecycle.html

Upvotes: 0

Vagner Franco
Vagner Franco

Reputation: 21

you should update the state like this

handleClick(){
    console.log(this.state)
    this.setState (state=>{
      return  { count: state.count + 1}
    })
}

because you return a object that you wish update not a integer

Upvotes: 1

Related Questions