Swipping scroll lock hook
A useful hook to lock/unlock scrolling when swiping horizontally in mobile devices.
The hook returns touch event handlers - touchStartHandler
, touchMoveHandler
,
touchEndHandler
, which needs to be wired up with the element targeted to
have isolated swiping action.
import { useCallback, useEffect, useState } from 'react';
/** A threshold value for y-swipe */
const Y_SWIPING_THRESHOLD = 3;
/**
* A hook to lock vertical scrolling of document body when swiping horizontally.
*/
export const useSwipingScrollLock = () => {
const [touchStartX, setTouchStartX] = useState(0);
const [preventingVerticalScroll, setPreventingVerticalScroll] = useState(false);
useEffect(() => {
document.body.style.overflow = preventingVerticalScroll ? 'hidden' : 'auto';
}, [preventingVerticalScroll]);
// cleanup & reset
useEffect(() => {
return () => {
document.body.style.overflow = 'auto';
};
}, []);
const touchStartHandler = () => (ev: TouchEvent) => {
const touch = ev.changedTouches[0];
setTouchStartX(touch.screenX);
};
const touchMoveHandler: any = useCallback(
(ev: TouchEvent) => {
const touch = ev.changedTouches[0];
const touchEndX = touch.screenX;
const swipeDistanceHorizontal = touchEndX - touchStartX;
if (Math.abs(swipeDistanceHorizontal) > Y_SWIPING_THRESHOLD) {
setPreventingVerticalScroll(true);
} else {
setPreventingVerticalScroll(false);
}
},
[touchStartX]
);
const touchEndHandler = () => setPreventingVerticalScroll(false);
return {
touchStartHandler,
touchMoveHandler,
touchEndHandler,
};
};