Skip to content
Advertisement

How to stop ReactJS countdown timer from re-rendering?

I’m currently using a simple Countdown Timer component. This is the code of the component:

import React, { useState, useRef, useEffect, useCallback } from 'react'


const Timer = ({time}) => {

    // We need ref in this, because we are dealing
    // with JS setInterval to keep track of it and
    // stop it when needed
    const Ref = useRef(null);

    // The state for our timer
    const [timer, setTimer] = useState('00:00:00');
    const number = 1000


    const getTimeRemaining = (e) => {
        var total = (Date.parse(e) - Date.parse(new Date())) / 1000;

        // calculate (and subtract) whole days
        var days = Math.floor(total / 86400);
        total -= days * 86400;

        // calculate (and subtract) whole hours
        var hours = Math.floor(total / 3600) % 24;
        total -= hours * 3600;

        // calculate (and subtract) whole minutes
        var minutes = Math.floor(total / 60) % 60;
        total -= minutes * 60;

        // what's left is seconds
        var seconds = total % 60;
        return {
            total, days, hours, minutes, seconds
        };
    }


    const startTimer = (e) => {
        let { total, days, hours, minutes, seconds }
                    = getTimeRemaining(e);
        if (total >= 0) {

            // update the timer
            // check if less than 10 then we need to
            // add '0' at the beginning of the variable
            setTimer(
                (days < 1 ? '00' : days)  + ':' +
                (hours > 9 ? hours : '0' + hours) + ':' +
                (minutes > 9 ? minutes : '0' + minutes) + ':'
                + (seconds > 9 ? seconds : '0' + seconds)
            )
        }
    }


    const clearTimer = (e) => {

        // If you adjust it you should also need to
        // adjust the Endtime formula we are about
        // to code next 
        setTimer('00:00:10');

        // If you try to remove this line the
        // updating of timer Variable will be
        // after 1000ms or 1sec
        if (Ref.current) clearInterval(Ref.current);
        const id = setInterval(() => {
            startTimer(e);
        }, 1000)
        Ref.current = id;
    }

    const getDeadTime = () => {
        let deadline = new Date();

        // This is where you need to adjust if
        // you entend to add more time
        deadline.setSeconds(deadline.getSeconds() + Math.floor(time));
        return deadline;
    }

    // We can use useEffect so that when the component
    // mount the timer will start as soon as possible

    // We put empty array to act as componentDid
    // mount only
    useEffect(() => {
        clearTimer(getDeadTime());
    }, []);

    // Another way to call the clearTimer() to start
    // the countdown is via action event from the
    // button first we create function to be called
    // by the button 

    return (
        <div className="App">
            <h2 className='text-3xl lg:text-4xl text-transparent bg-clip-text text-center bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500'>{timer}</h2>
        </div>
    )
}

export default Timer;

My issue is that everytime I refresh my page, the timer starts again. I understand this has something to do with react re-rendering the components and I need to move this to a higher level to save state, but I’m not sure exactly how to do that.

Also, I use the time as a sort of prop, where everytime a user creates a new listing on my website, a new timer starts for that particular listing.

So how exactly can I make my timer save state for already created listings, while at the same time allowing it to create new listings?

Thanks!

Advertisement

Answer

First of all, I’m not sure what do you mean by “refresh page”, if you mean that you hit ctrl+r and reload browser tab, the you restart your application entirely and it’s not about react state. In this case you need to store somewhere your current state and update your local state from that data after refresh.

So you need to save your timer start time in local storage or on server side so you would have an ability to initialize your timer using that time and it will continue running after page reload

Advertisement