Home > Software engineering >  How to clear internal inside useEffect hooks
How to clear internal inside useEffect hooks

Time:09-29

I have a component to implement countdown

if the timer is zero then the interval should stop, and it does not stop

my code

const CountDown = ({ endDate }) => {
    const [timeLeft, setTimeLeft] = React.useState(null);
    const { days, hours, minutes, seconds } = timeLeft || {};

    React.useEffect(() => {

        if (days   hours   minutes   seconds === 0) {
            clearInterval(interval);
            return;
        }

        if (days < 0 || hours < 0 || minutes < 0 || seconds < 0) {
            console.log('Countdown has expired');
            clearInterval(interval);
            return;
        }
        const interval = setInterval(() => {
                const now = new Date();
                const diff = endDate - now;
                const days = Math.floor(diff / (1000 * 60 * 60 * 24));
                const hours = Math.floor((diff / (1000 * 60 * 60)) % 24);
                const minutes = Math.floor((diff / 1000 / 60) % 60);
                const seconds = Math.floor((diff / 1000) % 60);
                setTimeLeft({ days, hours, minutes, seconds });

        }, 1000);

        return () => clearInterval(interval);
    }, [endDate]);
    if (days === 0 && hours === 0 && minutes === 0 && seconds === 0) {
        return <CountDownExpire />
    } else {
        console.log(days, hours, minutes, seconds);
    }


    return (
        <>
        </>
);
}

export default CountDown;

logs

0 0 0 11
0 0 0 10
0 0 0 9
0 0 0 8
0 0 0 7
0 0 0 6
0 0 0 5
0 0 0 4
0 0 0 3
0 0 0 2
0 0 0 1
-1 -1 -1 -1
-1 -1 -1 -2
-1 -1 -1 -3
-1 -1 -1 -4
-1 -1 -1 -5
-1 -1 -1 -6
-1 -1 -1 -7
-1 -1 -1 -8
-1 -1 -1 -9

code sandbox link: https://codesandbox.io/s/misty-morning-1h37q6?file=/src/countdown.jsx

if you inspect element, and check the logs, you will see that it is running on the background.

Thanks in advance!

CodePudding user response:

Your effect does reference days, hours, minutes, seconds from outside the effect, they can't help you clear the interval as the effect will only be executed when the dependency endDate changes. If they were dependencies, they would re-create the effect every time the interval ticks, so clear the interval.

Logic for clearing the interval needs to be inside the interval callback I think.

So the effect should be like this.

React.useEffect(() => {
    const interval = setInterval(() => {
        const now = new Date();
        const diff = endDate - now;
        if (diff <= 0) {
            clearInterval(interval);
        } else {
            const days = Math.floor(diff / (1000 * 60 * 60 * 24));
            const hours = Math.floor((diff / (1000 * 60 * 60)) % 24);
            const minutes = Math.floor((diff / 1000 / 60) % 60);
            const seconds = Math.floor((diff / 1000) % 60);
            setTimeLeft({ days, hours, minutes, seconds });
        }
    }, 1000);

    return () => clearInterval(interval);
}, [endDate]);

See the modified CodeSandbox, there is additional code to to initialize the time left.

  • Related