@@ -5,24 +5,57 @@ import { useEffect, useRef, useState } from 'react';
55 *
66 * @param callback The function to be executed at the specified interval.
77 * @param delay The delay (in milliseconds) between each execution of the callback function. If `null`, the interval is cleared(pause).
8+ * @param pauseWhenHidden Whether to pause the interval when the page becomes hidden. Defaults to true.
89 */
9- export function useInterval ( callback : ( ) => void , delay : number | null ) {
10+ export function useInterval (
11+ callback : ( ) => void ,
12+ delay : number | null ,
13+ pauseWhenHidden : boolean = true ,
14+ ) {
1015 const savedCallback = useRef < ( ) => any > ( null ) ;
16+ const [ isPageVisible , setIsPageVisible ] = useState ( ( ) =>
17+ typeof document !== 'undefined' ? ! document . hidden : true ,
18+ ) ;
1119
1220 useEffect ( ( ) => {
1321 savedCallback . current = callback ;
1422 } ) ;
1523
24+ // Handle page visibility changes
25+ useEffect ( ( ) => {
26+ if ( ! pauseWhenHidden ) return ;
27+
28+ const handleVisibilityChange = ( ) => {
29+ const visible = ! document . hidden ;
30+ setIsPageVisible ( ( prev ) => {
31+ if ( delay !== null && ! prev && visible ) {
32+ // Execute callback immediately when page becomes visible again
33+ savedCallback . current ?.( ) ;
34+ }
35+ return visible ;
36+ } ) ;
37+ } ;
38+
39+ document . addEventListener ( 'visibilitychange' , handleVisibilityChange ) ;
40+
41+ return ( ) => {
42+ document . removeEventListener ( 'visibilitychange' , handleVisibilityChange ) ;
43+ } ;
44+ } , [ pauseWhenHidden , delay ] ) ;
45+
1646 useEffect ( ( ) => {
1747 function tick ( ) {
1848 savedCallback . current ?.( ) ;
1949 }
2050
2151 if ( delay !== null ) {
22- let id = setInterval ( tick , delay ) ;
23- return ( ) => clearInterval ( id ) ;
52+ // Only check visibility if pauseWhenHidden is enabled
53+ if ( ! pauseWhenHidden || isPageVisible ) {
54+ let id = setInterval ( tick , delay ) ;
55+ return ( ) => clearInterval ( id ) ;
56+ }
2457 }
25- } , [ delay ] ) ;
58+ } , [ delay , pauseWhenHidden , isPageVisible ] ) ;
2659}
2760
2861/**
@@ -31,14 +64,16 @@ export function useInterval(callback: () => void, delay: number | null) {
3164 * @param calculator - A function that calculates the value.
3265 * @param delay - The delay in milliseconds between updates.
3366 * @param triggerKey - An optional key that triggers an immediate update when changed.
67+ * @param pauseWhenHidden - Whether to pause the interval when the page becomes hidden. Defaults to true.
3468 * @returns The updated value.
3569 */
36- export const useIntervalValue = (
37- calculator : ( ) => any ,
70+ export function useIntervalValue < T > (
71+ calculator : ( ) => T ,
3872 delay : number | null ,
3973 triggerKey ?: string ,
40- ) => {
41- const [ result , setResult ] = useState ( calculator ( ) ) ;
74+ pauseWhenHidden : boolean = true ,
75+ ) : T {
76+ const [ result , setResult ] = useState < T > ( calculator ) ;
4277
4378 useEffect ( ( ) => {
4479 if ( triggerKey ) {
@@ -47,10 +82,14 @@ export const useIntervalValue = (
4782 // eslint-disable-next-line react-hooks/exhaustive-deps
4883 } , [ triggerKey ] ) ;
4984
50- useInterval ( ( ) => {
51- const newResult = calculator ( ) ;
52- if ( newResult !== result ) setResult ( newResult ) ;
53- } , delay ) ;
85+ useInterval (
86+ ( ) => {
87+ const newResult = calculator ( ) ;
88+ if ( newResult !== result ) setResult ( newResult ) ;
89+ } ,
90+ delay ,
91+ pauseWhenHidden ,
92+ ) ;
5493
5594 return result ;
56- } ;
95+ }
0 commit comments