React Custom Hook: useSwipe
This challenge asks you to create a reusable React custom hook, useSwipe, that detects swipe gestures on a given element. Implementing this hook allows you to easily add swipe functionality to your React components, enabling features like horizontal scrolling, image galleries, or navigation controls. This is a common and useful pattern for creating interactive user interfaces.
Problem Description
You need to build a useSwipe hook that detects swipe gestures (both left and right) on a specified element. The hook should return an object containing a swipeLeft and swipeRight boolean flag, indicating whether a swipe in the respective direction has occurred since the last reset. The hook should also provide a resetSwipe function to reset the swipe flags to false.
Key Requirements:
- Gesture Detection: The hook must accurately detect swipe gestures. A swipe is defined as a movement of at least
minDistancepixels in a single direction (left or right) withinmaxTimemilliseconds. - Directional Recognition: The hook must differentiate between left and right swipes.
- Reset Functionality: The
resetSwipefunction must reset bothswipeLeftandswipeRightflags tofalse. - Event Handling: The hook should handle the necessary event listeners (touchstart, touchmove, touchend) to detect the swipe gesture.
- TypeScript: The hook must be written in TypeScript.
Expected Behavior:
- When a swipe is detected, the corresponding flag (
swipeLeftorswipeRight) should be set totrue. - The flags should remain
trueuntilresetSwipeis called. - Multiple swipes in the same direction should not continuously set the flag to
true. Once a swipe is detected, the flag remainstrueuntil reset. - The hook should not interfere with other event listeners on the element.
Edge Cases to Consider:
- Short Movements: Movements shorter than
minDistanceshould not be considered swipes. - Slow Movements: Movements that take longer than
maxTimeshould not be considered swipes. - Multi-Touch: The hook should primarily focus on single-touch swipe detection. Handling multi-touch gestures is not required for this challenge.
- Element Not Found: Handle the case where the element passed to the hook doesn't exist.
- Unmounting: Properly clean up event listeners when the component unmounts to prevent memory leaks.
Examples
Example 1:
Input: Element: <div ref={elementRef}></div>, minDistance: 50, maxTime: 200
User swipes right across the element, covering a distance of 75 pixels within 150 milliseconds.
Output: { swipeLeft: false, swipeRight: true }
Explanation: A right swipe exceeding the minimum distance and within the maximum time is detected, setting swipeRight to true.
Example 2:
Input: Element: <div ref={elementRef}></div>, minDistance: 25, maxTime: 100
User swipes left across the element, covering a distance of 10 pixels within 50 milliseconds.
Output: { swipeLeft: false, swipeRight: false }
Explanation: The swipe distance is less than the minimum distance, so no swipe is detected.
Example 3:
Input: Element: <div ref={elementRef}></div>, minDistance: 30, maxTime: 300
User swipes right across the element, covering a distance of 60 pixels within 400 milliseconds.
Output: { swipeLeft: false, swipeRight: false }
Explanation: The swipe time exceeds the maximum time, so no swipe is detected.
Constraints
minDistancemust be a positive integer (minimum: 1).maxTimemust be a positive integer (minimum: 1).- The hook should be performant and avoid unnecessary re-renders.
- The element passed to the hook must be a valid DOM element.
- The hook should not introduce any memory leaks.
Notes
- Consider using
useRefto store the element and the start position of the swipe. - Use
addEventListenerandremoveEventListenerto manage the event listeners. - Debouncing or throttling might be helpful to optimize performance, but is not strictly required for this challenge.
- Focus on the core swipe detection logic and directional recognition. Styling or visual feedback is not required.
- The
elementRefshould be a React ref object. The hook should accept this ref object as an argument.