3 mins read


Custom react hook for client idle detection:- useIdle


Implementation

 
import { useState, useEffect, useRef } from 'react';
 
/**
 * Hook that returns a boolean indicating whether the user is considered idle or not.
 * @param idleTime - The time in milliseconds after which the user is considered idle. Defaults to 25000 (25 seconds).
 * @returns `true` if the user is idle, `false` otherwise.
 */
const useIdle = (idleTime: number = 25000): boolean => {
  const [isIdle, setIsIdle] = useState(false);
  const idleTimeoutRef = useRef<number | null>(null);
 
  /**
   * Handles the idle event.
   */
  const handleIdle = () => {
    setIsIdle(true);
  };
 
  /**
   * Handles the activity event.
   */
  const handleActivity = () => {
    setIsIdle(false);
    if (idleTimeoutRef.current) {
      window.clearTimeout(idleTimeoutRef.current);
    }
    idleTimeoutRef.current = window.setTimeout(handleIdle, idleTime);
  };
 
  useEffect(() => {
    const events = [
      'mousemove',
      'keydown',
      'wheel',
      'DOMMouseScroll',
      'mouseWheel',
      'mousedown',
      'touchstart',
      'touchmove',
      'MSPointerDown',
      'MSPointerMove',
    ];
 
    const eventListenerOptions: AddEventListenerOptions = { passive: true };
 
    // Add event listeners for each event.
    for (const event of events) {
      window.addEventListener(event, handleActivity, eventListenerOptions);
    }
 
    // Set the initial idle timeout.
    idleTimeoutRef.current = window.setTimeout(handleIdle, idleTime);
 
    return () => {
      // Remove event listeners for each event.
      for (const event of events) {
        window.removeEventListener(event, handleActivity, eventListenerOptions);
      }
 
      // Clear the idle timeout if it hasn't fired yet.
      if (idleTimeoutRef.current) {
        window.clearTimeout(idleTimeoutRef.current);
      }
    };
  }, [idleTime]);
 
  return isIdle;
};
 
export default useIdle;