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>
);
}
}
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.
Unmounting. This method is called when a component is being removed from the DOM: 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With