Hone logo
Hone
Problems

Implementing a useIdle Hook in React

The useIdle hook provides a way to detect and react to periods of inactivity within a React component. This is useful for tasks like automatically saving data, clearing caches, or triggering animations after a user has stopped interacting with the application. This challenge asks you to implement this hook, providing a reliable mechanism for tracking user idle time.

Problem Description

You are tasked with creating a custom React hook called useIdle. This hook should track the time since the last user interaction (mouse movement, key press, touch event, etc.) and provide a way for components to react when the user becomes idle for a specified duration.

What needs to be achieved:

  • The hook should accept a timeout parameter (in milliseconds) which defines the idle time threshold.
  • The hook should return an object with the following properties:
    • isIdle: A boolean indicating whether the user is currently idle.
    • idleTimeout: A number representing the remaining time (in milliseconds) until the idle timeout is reached.
    • resetIdleTimer: A function that resets the idle timer.

Key Requirements:

  • The hook must accurately track user interactions.
  • The isIdle state should be updated correctly based on the elapsed time and the timeout value.
  • The idleTimeout value should reflect the remaining time until the idle timeout is reached.
  • The resetIdleTimer function should immediately reset the idle timer to its initial state.
  • The hook should handle component unmounting gracefully, preventing memory leaks.

Expected Behavior:

  • Initially, isIdle should be false and idleTimeout should be timeout.
  • Any user interaction (mouse move, key press, touch) should call resetIdleTimer.
  • If no interaction occurs for longer than the timeout, isIdle should become true and idleTimeout should be 0.
  • Calling resetIdleTimer should set isIdle to false and idleTimeout to timeout.

Edge Cases to Consider:

  • Very short timeouts (e.g., 100ms).
  • Rapid user interactions.
  • Component unmounting while the timer is running.
  • Handling different types of user interactions (mouse, keyboard, touch).

Examples

Example 1:

Input: timeout = 2000ms, initial state: no interactions
Output: { isIdle: false, idleTimeout: 2000, resetIdleTimer: function }
Explanation: The hook initializes with `isIdle` as `false` and `idleTimeout` set to the provided timeout value.

Example 2:

Input: timeout = 1000ms, user moves the mouse after 500ms
Output: { isIdle: false, idleTimeout: 1000, resetIdleTimer: function }
Explanation: The user interaction resets the idle timer, setting `isIdle` to `false` and `idleTimeout` back to 1000.

Example 3:

Input: timeout = 1000ms, no user interaction for 1500ms
Output: { isIdle: true, idleTimeout: 0, resetIdleTimer: function }
Explanation: Since no interaction occurred within the timeout period, `isIdle` becomes `true` and `idleTimeout` becomes 0.

Constraints

  • The timeout parameter must be a positive integer (greater than 0).
  • The resetIdleTimer function should be a stable reference (i.e., it shouldn't change on every render).
  • The hook should be performant and avoid unnecessary re-renders.
  • The hook should be compatible with functional components using React 18 or later.

Notes

  • Consider using useEffect and useRef to manage the timer and interaction tracking.
  • You'll need to add event listeners to track user interactions. Consider using addEventListener for mousemove, keydown, and touchstart events. Remember to remove these listeners when the component unmounts.
  • Think about how to handle the timer logic to avoid race conditions or inaccurate timing.
  • The idleTimeout value represents the remaining time until the timeout is reached, not the total time elapsed since the last interaction.
Loading editor...
typescript