Implementing a useDoubleClick Hook in React
This challenge asks you to create a custom React hook, useDoubleClick, that detects and handles double clicks on an element. This is a common requirement in user interfaces where you want to trigger a specific action only when a user clicks an element twice in quick succession, preventing accidental triggering of the action from a single click. The hook should return a function that, when applied to an event handler, will execute a provided callback only on double clicks.
Problem Description
You need to implement a useDoubleClick hook in TypeScript. This hook should take a callback function as an argument and return a new function that, when used as an event handler, will detect double clicks. The hook should:
- Track the time of the first click: Upon the first click, the hook should record the timestamp.
- Detect a double click: If a second click occurs within a specified time window (e.g., 300ms) of the first click, the provided callback function should be executed.
- Reset the timer: After the callback is executed (or if the time window expires), the hook should reset the timer and be ready to detect the next double click.
- Ignore single clicks: If the time between clicks exceeds the defined time window, the callback should not be executed.
Key Requirements:
- The hook must be written in TypeScript.
- The hook should accept a callback function as an argument.
- The hook should return a function that can be used as an event handler.
- The hook should implement a time window for double click detection (default: 300ms).
- The hook should handle edge cases gracefully (e.g., rapid clicks).
Expected Behavior:
- When the returned function is used as an event handler, a single click should not trigger the callback.
- Two clicks within the time window should trigger the callback.
- Two clicks outside the time window should not trigger the callback.
- The hook should not cause any memory leaks.
Examples
Example 1:
Input:
- Callback function: `() => console.log("Double clicked!")`
- Time window: 300ms
- Clicks: Single click, then another click 100ms later.
Output: No action.
Explanation: The time window is 300ms, and the second click occurred before that, so the callback is not executed.
Example 2:
Input:
- Callback function: `() => console.log("Double clicked!")`
- Time window: 300ms
- Clicks: Single click, then another click 200ms later.
Output: "Double clicked!" is logged to the console.
Explanation: The second click occurred within the 300ms time window, so the callback is executed.
Example 3: (Edge Case - Rapid Clicks)
Input:
- Callback function: `() => console.log("Double clicked!")`
- Time window: 300ms
- Clicks: Click, Click (very close together, within 100ms), Click (1 second later).
Output: "Double clicked!" is logged to the console, then nothing.
Explanation: The first two clicks are detected as a double click. The third click starts a new timer, but it's outside the window of the previous double click detection.
Constraints
- Time Window: The default time window for double click detection should be 300ms. The hook should not allow the time window to be negative.
- Callback Function: The callback function must be a function that takes no arguments.
- Performance: The hook should be performant and not introduce any significant overhead. Avoid unnecessary re-renders.
- TypeScript: The code must be valid TypeScript.
Notes
- Consider using
useStateanduseEffectto manage the timer and detect double clicks. - Think about how to reset the timer appropriately.
- Pay attention to potential race conditions if the clicks are very close together.
- You can use
Date.now()to get the current timestamp. - The hook should be reusable and not tightly coupled to any specific component.