I used setInterval
function that decreases the time
value by every second to develop the timer In ReactJS
.
And when I clicked the RESET
button before the time
value is 0, I expected the time
value to update back to 10 seconds, but it didn’t work in the setInterval
function.
How can I modify the time
value which updated outside the setInterval function to even within the setInterval function?
Here’s the code that I experiment with.
import React, { useState, useEffect, useRef } from 'react';
function Timer() {
let time = 10;
const [timeText, setTimeText] = useState(time);
const [timerOn, setTimerOn] = useState(false);
const handleReset = () => {
if (timerOn) {
/* This statement can not update the time value
within the Interval function. */
time = 10;
return;
}
setTimerOn(true);
let timerInterval = setInterval(() => {
setTimeText(time);
time--;
if (time < 0) {
clearInterval(timerInterval);
setTimerOn(false);
}
}, 1000);
};
return (
<div>
<h1>{timeText}</h1>
<button onClick={handleReset}>RESET</button>
</div>
);
}
export default Timer;
Here’s the desired result:
- If
RESET
button was clicked when the time value is greater than 1, it changes back to 10.
Current result:
[enter image description here][1]This question is related, but it doesn’t answer my question of how to update the time
value within the setInterval function.
2
Answers
I’ve checked your code again, because my first comment was actually wrong:
I made a few changes in your code:
It’s a problem with reference. Inside
setInterval
closure variabletime
refers to a different variable thantime
at the beginning ofhandleReset
. After first rerender variabletime
is created again, and this second version is used by the rest of the code, butsetInterval
still uses the same one variable from the beginning. Check out this examplePress first
RESET
and wait for rerender. Then press secondRESET
. Both setIntervals usetime
, but it is completely different time, because of the rerender between them.Try to press both of them at the same time, they get stuck, because since no-rerender between them, they will use the same
time
variable.You could make it work, by assuring that there will be only one
time
that changes only value, but notreference
(even after rerender). You can achieve it by usinguseRef
. However, keep in mind it’s more for educational(?) purpose than production-ready code.Approach of
@MoreTags
is a lot better for this kind of problem, but I wanted to show why it works the way it does.