rafik
rafik

Reputation: 31

setState causes unexpected trigger of event handler method

I am using a click event handler that calls setState. but it seems that setState causes a continous unexpected trigger of click event handler.

the state is composed of object (containing minutes and seconds) that should be decreased when i click the html element.

    const sessionLength = {min: 25,
      sec: 0}
    this.state = {
      breakLength: 5,
      sessionLength: sessionLength,
      sessionProcessed: sessionLength
    }

this is the click Event handler:

  startPomodoro(){
    this.setState(prevState=>({sessionProcessed: {...prevState.sessionProcessed, sec: prevState.sessionProcessed.sec - 1}}));
  };

and the JSX :

  render(){
    return(
      <div class="ml-5">
        <h1>Test</h1>
        <div>Session</div>
        <div><strong id="session">{this.state.sessionLength.min}:{this.state.sessionLength.sec}</strong></div>
        <div><i id="play" class="fa fa-play" onClick={this.startPomodoro()}></i> <i id="pause" class="fa fa-pause" onClick={this.pausePomodoro()}></i></div>
      </div>
    )
  }

As it display nothing, i have added an alert statement in the click event handler (startPomodoro) and it executes the startPomodoro event handler without me clicking.

Upvotes: 0

Views: 84

Answers (3)

TopWebGhost
TopWebGhost

Reputation: 335

Regarding the above answers, passing arrow function (onClick={ () => this.startPomodoro() }) will perfectly work. If you are passing a callback, you should bind callback function to this reference. Like this: onClick={ this.startPomodoro.bind(this) }

Upvotes: 0

Tiago Moreira
Tiago Moreira

Reputation: 7

When calling an handler, you have two options:

  • passing a callback ( best option )
  • declaring an anonymous function on render


Passing a callback onClick={this.startPomodoro}

Declaring an anonymous function onClick={() => this.startPomodoro()}

Take in consideration that if you declare an anonymous function it can cause some performance issues, as mentioned in the docs: https://reactjs.org/docs/handling-events.html

The problem with this syntax is that a different callback is created each time the component renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.

Upvotes: 0

asliwinski
asliwinski

Reputation: 1704

You are calling the handler (startPomodoro()) instead of just passing it (startPomodoro). Change your code to:

<i id="play" class="fa fa-play" onClick={this.startPomodoro}></i> <i id="pause" class="fa fa-pause" onClick={this.pausePomodoro}></i>

Upvotes: 2

Related Questions