Issue
I have a component where I am decrementing a value contained in a state variable, every second, using a useState hook :
import React, { useEffect, useState } from "react";
import { FC } from "react";
interface ITimerProps {
remainingSeconds: number;
}
const Timer: FC<ITimerProps> = ({ remainingSeconds = 10 }) => {
const [remainingTime, setRemainingTime] = useState(remainingSeconds);
useEffect(() => {
const timer = setInterval(() => {
decrementTime();
}, 1000);
return () => {
clearInterval(timer);
};
}, [remainingSeconds]);
function decrementTime (): void {
if (remainingTime > 0) {
setRemainingTime((currentTime) => currentTime - 1);
}
console.log("function gets called, state is : " + remainingTime);
};
return <div>{remainingTime}</div>;
};
export default Timer;
remainingTime ,which gets rendered, is indeed decremented every second, and in the developer tools, I can see that the state is updating.
But the console.log() inside the decrementTime function always display a value of 10.
The if statement within decrementTime function also always checks true, as it seems that when being read within this function, the state is always 10.
Is there something that I'm missing here ? Thanks
Solution
Thats because the function itself that you are calling in the setInterval is not updating. You have to append that function to the dependency array of the useEffect hook. in order to avoid the eslint warning wrap the decrementTime function with the useCallback hook (doesn't make a difference because the function will change anyway on every render in that case).
import React, { useCallback, useEffect, useState } from "react";
import { FC } from "react";
interface ITimerProps {
remainingSeconds: number;
}
const Timer: FC<ITimerProps> = ({ remainingSeconds = 10 }) => {
const [remainingTime, setRemainingTime] = useState(remainingSeconds);
const decrementTime = useCallback(() => {
if (remainingTime > 0) {
setRemainingTime((currentTime) => currentTime - 1);
}
console.log("function gets called, state is : " + remainingTime);
}, [remainingTime]);
useEffect(() => {
const timer = setInterval(() => {
decrementTime();
}, 1000);
return () => clearInterval(timer);
}, [remainingSeconds, decrementTime]);
return <div>{remainingTime}</div>;
};
export default Timer;
Answered By - PRSHL
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.