How to keep component running in background in react?

Viewed 925

I have a clock(interval) component where the time starts when a user visits the webpage but when the user move to other page and comes back to the clock page then the timer starts from beginning again.

How can I keep the Clock component running in background so no matter which webpage the user visits, the timer should keep going?

Thank you in advance

CLOCK COMPONENT

function Clock(props) {

    const [time, setTime] = useState(0);

    const run = true;

    useEffect(()=>{
        if (run=== true && time < 1440){
            var timerID = setInterval(() => tick(time),1000);

            return function cleanup(){
                clearInterval(timerID);
            };
        }
    },[run, time]);

    function tick(time){
        setTime(time + 10);
        console.log(time);
    }

    return (
        <div className="clock-space">
            <div className="clock">{time}</div>            
        </div>
    );
}

App Component (that calls clock comp)

return (
            <div className="box">
                <Header />
                <PageMenu name={this.state.page} data={this.changePageNameToDefault.bind(this)}/>
                <Clock />
                {renderComp}
            </div>
1 Answers

There is no running in the background. I guess the issue here is that you somehow initiate a rerender of the component. And it depends on what kind of routing you use inside your application and if it should remember the time on a revisit/reload of the page.

If you use some kind of router (react-router, ...), you might just refactor your code so the Clock-Component is outside the render-procedure of the router. Otherwise you might want to use a context (useContext, createContext), which stores your timer. Something along the following lines:

// TimerContext.tsx
const TimerContext = React.createContext();

const TimeProvider = (props) => {
    const [time, setTime] = useState(0);
    const run = true;

    useEffect(()=>{
        if (run=== true && time < 1440){
            var timerID = setInterval(() => tick(time),1000);

            return function cleanup(){
                clearInterval(timerID);
            };
        }
    },[run, time]);

    function tick(time){
        setTime(time + 10);
        console.log(time);
    }


    const value = {
        run,
        time
    }
    return <TimerContext.Provider value={value} {...props} />
}

const useTimer = () => useContext(TimerContext)
// ClockComponent.tsx
const Clock = (props) => {
    const {time} = useTimer();

    return (
        <div className="clock-space">
            <div className="clock">{time}</div>            
        </div>
    );
}

Don't forget to render the TimeProvider somewhere on the top of your render hierarchy.

In case you don't have a routing framework or have issues with reloading, you have to work with localStorage (or some other kind of client storage). There really is no other way (except communication with a server) to keep up the timer navigating your page.

You might also combine both approaches.

Related