Hone logo
Hone
Problems

Implementing a useLongPress Hook in React

Creating a reusable useLongPress hook in React allows developers to easily detect and respond to long press events on interactive elements. This is particularly useful for mobile applications or scenarios where a longer touch signifies a different action than a simple tap (e.g., opening a context menu, triggering a delete confirmation). This challenge asks you to implement such a hook, providing a clean and functional way to handle long press gestures.

Problem Description

You are tasked with creating a custom React hook called useLongPress. This hook should accept a delay (in milliseconds) as an argument and return an object containing the following functions:

  • onLongPress: A function that should be attached as an event handler to the element you want to monitor for long presses.
  • onPressEnd: A function to be called when the press is released.
  • onPressStart: A function to be called when the press begins.
  • cancelLongPress: A function to immediately cancel any ongoing long press timer.

The hook should:

  1. Start a timer: When onPressStart is called, start a timer with the provided delay.
  2. Execute onLongPress: If the timer completes (the user holds their finger down for the specified delay), call the provided onLongPress callback function.
  3. Cancel the timer: When onPressEnd is called (the user lifts their finger), cancel the timer, preventing the onLongPress callback from being executed.
  4. Provide callbacks: onPressStart and onPressEnd should be called immediately when the press starts and ends, respectively, regardless of whether the long press delay is met.
  5. Handle multiple presses: The hook should be able to handle multiple long press events without interference.

Examples

Example 1:

Input: delay = 500ms, onLongPress = () => console.log("Long press detected!")
  • User presses the element. onPressStart is called.
  • User holds the press for 500ms. onLongPress is called.
  • User releases the press. onPressEnd is called.

Example 2:

Input: delay = 250ms, onLongPress = () => alert("Context Menu"), onPressStart = () => console.log("Press started"), onPressEnd = () => console.log("Press ended")
  • User presses the element. onPressStart is called.
  • User holds the press for 100ms.
  • User releases the press. onPressEnd is called. onLongPress is not called.

Example 3: (Edge Case - Rapid Press and Release)

Input: delay = 1000ms, onLongPress = () => console.log("Very long press!")
  • User presses the element. onPressStart is called.
  • User releases the press after 200ms. onPressEnd is called. onLongPress is not called.

Constraints

  • The delay must be a positive integer (greater than 0).
  • The onLongPress, onPressStart, and onPressEnd callbacks should be functions.
  • The hook should not cause memory leaks. Ensure proper cleanup of timers.
  • The hook should work correctly in various React component types (functional components, class components).
  • The hook should be performant and avoid unnecessary re-renders.

Notes

  • Consider using setTimeout and clearTimeout to implement the timer functionality.
  • Use the useEffect hook to manage the timer and its cleanup.
  • Think about how to handle the component unmounting while a timer is running to prevent errors.
  • The cancelLongPress function should be provided to allow external cancellation of the long press timer. This is useful for scenarios where you want to preempt a long press action based on other events.
  • Ensure that the onPressStart and onPressEnd callbacks are always called, regardless of whether the long press delay is met. This provides consistent feedback to the user.
Loading editor...
typescript