Hone logo
Hone
Problems

Implementing a useTimeout Hook in React

The useTimeout hook is a utility that allows you to execute a function after a specified delay, similar to setTimeout but with React's lifecycle management. This is particularly useful for tasks like debouncing, rate limiting, or triggering actions after a user interaction, ensuring clean component updates and preventing unnecessary re-renders. Your task is to implement this hook, ensuring it handles cleanup properly and integrates seamlessly with React's re-rendering cycle.

Problem Description

You need to implement a custom React hook called useTimeout that accepts two arguments:

  1. timeout: A number representing the delay in milliseconds before the provided function is executed.
  2. callback: A function to be executed after the specified timeout.

The hook should:

  • Set up a timeout using setTimeout when the component mounts or when the timeout or callback values change.
  • Clear the timeout using clearTimeout when the component unmounts or when the timeout or callback values change. This prevents memory leaks and unexpected behavior.
  • Return a boolean value indicating whether the timeout is currently active.

Key Requirements:

  • The hook must be written in TypeScript.
  • The timeout should be cleared before a new timeout is set if the timeout or callback values change.
  • The callback function should be called with the same arguments it was defined with.
  • The hook should handle edge cases gracefully, such as a timeout value of 0.

Expected Behavior:

  • When the component mounts, the timeout is initiated.
  • When the component unmounts, the timeout is cleared.
  • If the timeout value changes, the existing timeout is cleared, and a new timeout is initiated with the new value.
  • If the callback function changes, the existing timeout is cleared, and a new timeout is initiated with the new callback.
  • The callback function is executed after the specified timeout has elapsed.
  • The returned boolean value accurately reflects whether a timeout is currently active.

Edge Cases to Consider:

  • timeout value is 0: The callback should be executed immediately.
  • callback is null or undefined: The hook should not attempt to execute a non-existent function.
  • Component unmounts before the timeout completes: The timeout should be cleared.
  • Rapid changes in timeout or callback: The hook should efficiently manage multiple timeouts without creating memory leaks.

Examples

Example 1:

Input: timeout = 2000, callback = () => console.log("Timeout executed!");
Output: Initially returns true, after 2000ms returns false, and logs "Timeout executed!" to the console.
Explanation: A timeout is set for 2000ms. After 2000ms, the callback is executed, and the timeout is cleared.

Example 2:

Input: timeout = 1000, callback = () => console.log("Timeout executed!");, timeout changes to 3000 after 500ms.
Output: Initially returns true, after 3000ms returns false, and logs "Timeout executed!" to the console.
Explanation: A timeout is set for 1000ms. Before it completes, the timeout value changes to 3000ms. The initial timeout is cleared, and a new timeout is set for 3000ms. After 3000ms, the callback is executed, and the timeout is cleared.

Example 3:

Input: timeout = 0, callback = () => console.log("Timeout executed!");
Output: Immediately returns false, and logs "Timeout executed!" to the console.
Explanation: A timeout with a value of 0 is set, which executes the callback immediately.

Constraints

  • The timeout value must be a non-negative number.
  • The callback function must be a function or null/undefined.
  • The hook should be performant and avoid unnecessary re-renders.
  • The implementation should be concise and readable.

Notes

  • Consider using useEffect to manage the timeout lifecycle.
  • Pay close attention to how you clear the timeout to prevent memory leaks.
  • Think about how to handle changes in the timeout and callback values efficiently.
  • The returned boolean value is a useful indicator of the timeout's state and can be used for conditional rendering or other purposes.
Loading editor...
typescript