From 00bcd0c62fd83e53d8da1a8a1a7354774a8e21f6 Mon Sep 17 00:00:00 2001 From: katspaugh Date: Thu, 15 Feb 2024 17:36:35 +0100 Subject: [PATCH] Refactor: don't poll data in background tabs --- src/hooks/__tests__/useIntervalCounter.test.ts | 8 +++++--- src/hooks/useIntervalCounter.ts | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/hooks/__tests__/useIntervalCounter.test.ts b/src/hooks/__tests__/useIntervalCounter.test.ts index 8b7b048d13..ee899d24da 100644 --- a/src/hooks/__tests__/useIntervalCounter.test.ts +++ b/src/hooks/__tests__/useIntervalCounter.test.ts @@ -1,6 +1,8 @@ import { act, renderHook } from '@testing-library/react' import useIntervalCounter from '../useIntervalCounter' +global.requestAnimationFrame = (callback: any) => setTimeout(callback, 0) + describe('useIntervalCounter', () => { beforeAll(() => { jest.useFakeTimers() @@ -13,13 +15,13 @@ describe('useIntervalCounter', () => { expect(result.current[1]).toBeInstanceOf(Function) act(() => { - jest.advanceTimersByTime(100) + jest.advanceTimersByTime(200) }) expect(result.current[0]).toBe(1) act(() => { - jest.advanceTimersByTime(100) + jest.advanceTimersByTime(200) }) expect(result.current[0]).toBe(2) @@ -29,7 +31,7 @@ describe('useIntervalCounter', () => { const { result } = renderHook(() => useIntervalCounter(100)) act(() => { - jest.advanceTimersByTime(100) + jest.advanceTimersByTime(200) }) expect(result.current[0]).toBe(1) diff --git a/src/hooks/useIntervalCounter.ts b/src/hooks/useIntervalCounter.ts index 5a3ad03b84..7cc5b87853 100644 --- a/src/hooks/useIntervalCounter.ts +++ b/src/hooks/useIntervalCounter.ts @@ -8,8 +8,19 @@ const useIntervalCounter = (interval: number): [number, () => void] => { }, [setCounter]) useEffect(() => { - const timerId = setTimeout(() => setCounter(counter + 1), interval) - return () => clearTimeout(timerId) + let reqFrameId: number + const timerId = setTimeout(() => { + // requestAnimationFrame prevents the timer from ticking in a background tab + reqFrameId = requestAnimationFrame(() => { + setCounter(counter + 1) + }) + }, interval) + return () => { + clearTimeout(timerId) + if (reqFrameId) { + cancelAnimationFrame(reqFrameId) + } + } }, [counter, interval]) return [counter, resetCounter]