Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
120
rated 0 times [  123] [ 3]  / answers: 1 / hits: 31148  / 8 Years ago, wed, november 9, 2016, 12:00:00

I have a timer using setInterval() in a React component and I'm unsure what the best practices are in order to start and stop this interval in respect to using state. I'm running into some asynchronous issues with that.



Let's say I have a set of links in my React component that render and execute the callback fine:



let links = [10, 50, 100, 500, 1000].map((num) => {
return(
<Link key={num} onClick={(e) => this.switchNums(num)} to={`/somePath/${num}`}>{num}</Link>
)
})


Here's the switchNums() function, where i want it to reset an existing timer:



switchNums(num){
this.stopTimer()
this.reset(num)
}


Here's startTimer(), stopTimer() and reset():



startTimer(){
if(!this.state.timerId){
let timerId = setInterval(()=>{
let timer = this.state.timer + 1
this.setState({
timer: timer,
timerId: timerId
})
}, 1000)
}
}

stopTimer(){
clearInterval(this.state.timerId)
this.setState({timerId:null})
}

reset(size){
this.setState({
gameOver: false,
counter: 0,
correct: 0,
numbers: this.getRandomNumbers(size),
timer: 0
}, this.startTimer())
}


One of the bugs is clicking on the links rapidly will cause multiple intervals to fire despite the if condition in startTimer(). I'm guessing this has to do with the asynchronous nature of setState(). Another bug (and I think related) is that when i click slowly, it only starts the interval every other time.



Can anyone shed some light on this? Or what they've done to circumvent asynchronous issues with setState being used in conjunction with setInterval(any way set state can return a promise?), Or which lifecycle methods would be best for this type of situation?


More From » reactjs

 Answers
46

I think the biggest flaw here is that you're using state to store your interval. While technically possible, I see no reason why you would actually want to do that.



Instead, just use a local variable to your component:



startTimer(){
if(!this.timerId){
this.timerId = setInterval(()=>{
//your function
}, 1000);
}
}

stopTimer(){
clearInterval(this.timerId);
}


So I don't think you need to use the state at all here for your timer. You have some other general questions in your post though that are related to state, and I'll try to answer those below. Just bear in mind that they are irrelevant in solving your particular issue.






What have they've done to circumvent asynchronous issues with setState()?



You can use a callback to execute code after the state has been set. There's a section of the official docs about this; here's what it says:




The second parameter is an optional callback function that will be executed once setState is completed and the component is re-rendered.




setState(nextState, callback);





Which lifecycle methods would be best for this type of situation?



The same section of the doc as above continues:




Generally we recommend using componentDidUpdate() for such logic instead.




If you have multiple setState in your function, and you want to execute specific code after a specific event, I think you're fine using the callback. For more general purposes use the life-cycle method above.


[#60123] Monday, November 7, 2016, 8 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kaceyr

Total Points: 510
Total Questions: 97
Total Answers: 116

Location: Solomon Islands
Member since Fri, Oct 8, 2021
3 Years ago
kaceyr questions
;