Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping a timer in componentWillUnmount

I'm making a little countdown timer as a React exercise (for myself, not a class or anything) and everything works fine (although notes are always welcome) except that I noticed that it keeps counting down even after the component is unmounted.

So now I want to make it stop on unmount, but can't seem to get it right. What is the protocol for stopping setInterval on unmount? Here's what I have:

class TimerVal extends Component {
  constructor(props) {
    super(props)
    this.state = {
      timeToGo: 30
    }
  }
  secondsToMMSS(seconds) {
    //returns "mm:ss"
  }
  componentDidMount() {
    setInterval(
      () => this.setState({
        timeToGo: this.state.timeToGo - 1
      }),
      1000
    )
  }
  componentWillUnmount() {
    () => this.setState({
      timeToGo: undefined
    })
  }
  render() {
    // styles
    console.log(this.state)
    const count = ( this.state.timeToGo > 0 ) ? this.secondsToMMSS(this.state.timeToGo) : "00:00"
    console.log(count)
    return(
      <div style={timerStyle}>
        <span style={timerSpanStyle}>
          {count}
        </span>
      </div>
    );
  }
}
like image 636
TrivialCase Avatar asked Sep 03 '17 15:09

TrivialCase


People also ask

How do you stop a timer in React?

In our other event handler "stopTimer()", I call on a function called "clearInterval()". You can think of this function as the opposite cousin of "setInterval()" whereas setInterval() starts the timer, clearInterval() clears it. I then pass our function "setSeconds()" to clearInterval and pass in a zero.

What is unmounting a component?

Unmounting. This method is called when a component is being removed from the DOM: componentWillUnmount()

When should I use componentWillUnmount?

componentWillUnmount is the last function to be called immediately before the component is removed from the DOM. It is generally used to perform clean-up for any DOM-elements or timers created in componentWillMount . At a picnic, componentWillUnmount corresponds to just before you pick up your picnic blanket.

Is componentWillUnmount necessary?

Nope, it is not necessary in this case. However, if you use some timeout functions then you have to clear them before unmounting your component.


1 Answers

A few things. First of all, this isn't doing anything:

() => this.setState({
  timeToGo: undefined
})

You're just defining an anonymous function and doing nothing with it. Next, don't just set timeToGo to undefined when the countdown stops. The interval will just keep on going. Instead, clear the interval:

this.interval = setInterval(
  () => this.setState({
    timeToGo: this.state.timeToGo - 1
  }),
  1000
)

Then in componentWillUnmount:

clearInterval(this.interval)

This will cleanly clear the countdown. Finally, clear the interval when the countdown reaches 0, or else it will keep running. That costs resources:

this.interval = setInterval(
  () => {
    if(this.state.timeToGo > 0) {
      this.setState(prevState => ({
        timeToGo: prevState.timeToGo - 1
      }))
    } else {
      clearInterval(this.interval)
    }
  },
  1000
)

This will clear the interval once it reaches 0. Also, note that I used prevState. Since setState is asynchronous this ensures that it's accessing the correct state.

like image 59
Andrew Li Avatar answered Sep 24 '22 16:09

Andrew Li