Currently, I am trying to build a timer, but it stops after one second. I am trying to use hooks in React and I am trying to figure out how to implement useEffect into my startTimer function so it can countdown.
function InputTimer() {
const [timerOn, setTimerOn] = useState(false);
const [timerStart, setTimerStart] = useState(0);
const [timerTime, setTimerTime] = useState(0);
let timer;
const startTimer = () => {
setTimerOn(true);
setTimerStart(0);
setTimerTime(0);
timer = setInterval(() => {
const newTime = timerTime - 1;
if (newTime >= 0) {
setTimerTime(newTime);
} else {
clearInterval(timer);
setTimerOn(false);
alert("Countdown Ended");
}
}, 1000);
}
}
CodePudding user response:
It appears your code is working.
However, you just set the time to be zero, so after a second, it exits.
To properly test, your code, set the start time to 10 seconds: setTimerTime(10);
Full Code
function InputTimer() {
const [timerOn, setTimerOn] = useState(false);
const [timerStart, setTimerStart] = useState(0);
const [timerTime, setTimerTime] = useState(0);
let timer;
const startTimer = () => {
setTimerOn(true);
setTimerStart(10); // Change this line
setTimerTime(0);
timer = setInterval(() => {
const newTime = timerTime - 1;
if (newTime >= 0) {
setTimerTime(newTime);
} else {
clearInterval(timer);
setTimerOn(false);
alert("Countdown Ended");
}
}, 1000);
}
}
CodePudding user response:
You've closed over the timerTime
value in the interval callback scope, it never changes.
Here's a minimal example of your logic that runs:
Split the logic up, use the interval callback to decrement the time and use a useEffect
hook to check the termination condition. Use a React ref to store the timer reference.
function InputTimer() {
const [timerTime, setTimerTime] = useState(10);
const timerRef = useRef();
useEffect(() => {
return () => clearInterval(timerRef.current);
}, []);
useEffect(() => {
if (timerTime <= 0) {
clearInterval(timerRef.current);
alert("Countdown Ended");
}
}, [timerTime]);
const startTimer = () => {
setTimerTime(10);
timerRef.current = setInterval(() => {
setTimerTime(time => time - 1);
}, 1000);
}
return (
<>
<div>Time: {timerTime}</div>
<button type="button" onClick={startTimer}>Start</button>
</>
)
}