setInterval freezes react app after some time (couple days)

Viewed 494

I have a react app (nextjs) and show a QR code that refreshes itself every 5 seconds and a clock which updates every 1 second. Further, I have added service-worker to enable PWA and offline support.

After running it for a couple hours, or even days, out of nowhere the app freezes and does not update anymore.

If relevant, it happens on mobile devices (Android), maybe there is something up with energy saver mode or so? Even if I pull down to refresh, the react app does not change! The only thing is exiting Chrome and then opening again.

I really have no clue what could be the cause of the issue.

RAM usage seems to be the same for all the time:

RAM

There are no network calls, everything is local, this is the example of the clock function that I use:

useEffect(() => {
    const interval = setInterval(() => {
      setTime(new Date());
    }, 1000);
    return () => {
      clearInterval(interval);
    };
  }, []);

The interval function that I use for the QR code is:

useEffect(() => {
    const interval = setInterval(() => {
      setOptions((prev) => ({
        ...prev,
        data: generateQrCodeString(),
      }));
    }, 5000);

    return () => {
      clearInterval(interval);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

I use this qrcode lib: https://www.npmjs.com/package/qr-code-styling

Does anyone have any suggestions? Appreciate any help!

Edit:

I tried the useInterval hook from here https://usehooks-ts.com/react-hook/use-interval and it seems to be working smoother, but after a couple hours/days, it still freezes.

Updated code:

useInterval(() => {
    setTime(new Date());
  }, 1000);
useInterval(() => {
    setOptions((prev) => ({
      ...prev,
      data: generateQrCodeString(),
    }));
  }, 5000);
3 Answers

Try removing the pwa and check whether it still freezes or not. For me, it was cache-control headers with some caching values (for images), all I did was set cache-control to 0 and let pwa handle the caching by itself.

ServiceWorkers are specifically designed to be short-lived. The browser may terminate the service worker at any time.

Basically, you can't use setInterval or setTimeout reliably in a service worker. The supported way to keep a service worker alive is passing a promise to waitUntil/respondWith, but even then the browser may time out the promise and terminate the worker.

More about waitUnitl

So from your explanation what is happening is that you are caught in infinite loop with the setInterval method.

You can achieve what you wanted to do without react-hooks (useEffect or useInterval). Check the code below if it will help you.

let seconds = 5;
const interval = setInterval(() => {
  seconds = seconds - 1;
  console.log(seconds);
  if(seconds <=0){
    clearInterval(interval);
  }
}, 1000);

Related