Hone logo
Hone
Problems

Create a useDebounce Hook in React

The useDebounce hook is a common utility in React applications to control the rate at which functions are executed. It's particularly useful for handling events like search input, window resizing, or scroll events where you want to avoid triggering an expensive operation on every single event fire. This challenge asks you to implement this hook from scratch.

Problem Description

You are tasked with creating a reusable useDebounce hook in React using TypeScript. This hook should accept a function and a delay (in milliseconds) as arguments. It should return a debounced version of the function that will only be executed after the specified delay has passed since the last time the debounced function was called.

What needs to be achieved:

  • Create a custom React hook named useDebounce.
  • The hook should accept two arguments:
    • func: The function to be debounced. This function can accept any number of arguments.
    • delay: The delay in milliseconds before the function is executed.
  • The hook should return a debounced function.
  • The debounced function should, when called, prevent the original function from being executed until the specified delay has elapsed since the last call to the debounced function.

Key Requirements:

  • The hook must use the useState and useEffect hooks from React.
  • The debounced function should maintain the correct this context if the original function is a method of a class component.
  • The debounced function should pass any arguments provided to it to the original function.
  • The hook should handle the case where the component unmounts before the delay has elapsed.

Expected Behavior:

  • Calling the debounced function multiple times within the delay period should only execute the original function once, after the delay has passed since the last call.
  • If the component unmounts while the delay is active, the original function should not be executed.

Edge Cases to Consider:

  • delay being 0. In this case, the function should be executed immediately.
  • func being null or undefined. The hook should handle this gracefully (e.g., return a no-op function).
  • The original function taking arguments.
  • The original function being a method of a class component.

Examples

Example 1:

Input:
func: () => console.log("Search executed!");
delay: 500

Output: A debounced function. Calling this debounced function repeatedly within 500ms will only log "Search executed!" once after 500ms of inactivity.

Explanation: The useDebounce hook creates a debounced version of the provided function. If the debounced function is called multiple times within 500ms, the timer resets each time. Only after 500ms of inactivity will the original function be executed.

Example 2:

Input:
func: (searchTerm: string) => console.log("Searching for:", searchTerm);
delay: 300

Output: A debounced function that accepts a string argument.

Explanation: The debounced function will accept the string argument and pass it to the original function when it's finally executed.

Example 3: (Edge Case)

Input:
func: null;
delay: 100;

Output: A no-op function that does nothing when called.

Explanation: The hook gracefully handles the case where the function to be debounced is null or undefined.

Constraints

  • The delay must be a non-negative integer.
  • The hook must be implemented using only standard React hooks (useState, useEffect).
  • The debounced function should be memoized to prevent unnecessary re-renders.
  • The hook should be performant and avoid creating unnecessary closures or re-renders.

Notes

  • Consider using setTimeout and clearTimeout to manage the delay.
  • Think about how to handle the this context correctly if the original function is a method of a class component. While less common in modern React, it's good to handle this case.
  • The goal is to create a robust and reusable useDebounce hook that can be used in various React components. Focus on clarity, correctness, and efficiency.
Loading editor...
typescript