Swipping scroll lock hook
| 1 min read
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,
};
};