Here on this article we will discuss about creating a swipeable div using Reactjs. Here is the following video of what we will be creating on below article:
Above is the demo we are goona create , so let’s get started fellow coders.
Required package
The package we will be using to achieve the above functionality is react-swipeable
.
Using npm
To install react-swipeable
with npm, run:
npm install react-swipeable
Using Yarn
To install react-swipeable
with Yarn, run:
yarn add react-swipeable
Using react swipeable
Using react swipeable in ReactJs is easy! Follow these simple steps below:
- Import
useSwipeable
hook fromreact-swipeable
- Set the swipe handlers you care about
- Spread the handlers onto an html tag to bind to the events
Here is a code demonstration for it:
import { useSwipeable } from 'react-swipeable';
const handlers = useSwipeable({
onSwiped: (eventData) => console.log("User Swiped!", eventData),
...config,
});
return
const handlers = useSwipeable({
onSwiping: handleSwap,
onTouchEndOrOnMouseUp: handleEnd,
...config,
});
OnSwiping triggers During swiping the div or any element that you injected the handlers in. While onTouchEndOrOnMouseUp executes when the user touch ends . These both are essential for creating what we want.
Now we use useRef state to change the transform property of the div that we want. For your info, we injected handlers into the parent element while the useRef to the div that the user will be swiping. I used it this way since this package adds its own useRef hook to the element where we use handlers on . Well i do have the solution to that if you want to use your own useRef hook on same element, do keep reading the article to see how it can be done.
We also use useState hook to keep in track the swiping direction and amount of pixels swiped from starting position which will be helpful . We will also be initializing two constants i.e Maximum pixels user can swipe the div so it wont look overflowed and Minimum pixels users must swipe so the swipe would be successful . You can do change these values according to your taste though.
const swipeRef = useRef(null);
const [swipeState, setSwipeState] = useState({ direction: null, X: 0 });
const SWIPE_THRESHOLD = 200; // Maximum swipe distance in pixels
const SNAP_DISTANCE = 70; // Distance to snap on swipe end
Now onto handleSwap function:
const handleSwap = ({ deltaX, dir }) => {
const swipeDiv = swipeRef.current;
const minMaxDelta = Math.max(
-SWIPE_THRESHOLD,
Math.min(SWIPE_THRESHOLD, deltaX)
);
console.log(minMaxDelta);
setSwipeState({ direction: dir, X: minMaxDelta });
swipeDiv.style.transform = `translate(${minMaxDelta}px)`;
};
Function Parameters
{ deltaX, dir }
: The destructured argument represents the swipe data:deltaX
: The distance in pixels that the user has swiped horizontally.dir
: The direction of the swipe, either"Left"
or"Right"
.
minMaxDelta
Here’s how it works step by step:
Math.min(SWIPE_THRESHOLD, deltaX)
: This function makes sure thatdeltaX
does not exceed the positive threshold (SWIPE_THRESHOLD
). IfdeltaX
is greater thanSWIPE_THRESHOLD
, this function returnsSWIPE_THRESHOLD
(which is 200 in my case); otherwise, it returnsdeltaX
.Math.max(-SWIPE_THRESHOLD, ...)
: This function ensures thatdeltaX
does not fall below the negative threshold (-SWIPE_THRESHOLD
). If the result fromMath.min
is less than-SWIPE_THRESHOLD
, this function returns-SWIPE_THRESHOLD
; otherwise, it returns the result fromMath.min
.
So, minMaxDelta
will always lie between -SWIPE_THRESHOLD
and SWIPE_THRESHOLD
, effectively clamping deltaX
within our required range.
Now onto handleEnd function:
const handleEnd = () => {
const swipeDiv = swipeRef.current;
const { direction, X } = swipeState;
if(direction==="Right" && X>=SNAP_DISTANCE){
swipeDiv.style.transform = `translateX(70px)`;
return;
}
if(direction==="Left" && X<=SNAP_DISTANCE){
swipeDiv.style.transform = `translateX(-70px)`;
return;
}
};
const { direction, X } = swipeState;
:- This destructures the
swipeState
object, which holds information about the current swipedirection
represents the direction of the swipe (either “Right” or “Left”), andX
represents the amount of pixel a user swiped.
- This destructures the
if (direction === "Right" && X >= SNAP_DISTANCE)
:- This checks if the swipe direction is “Right” and if the
X
distance of the swipe is greater than or equal to 70px (SNAP_DISTANCE
). If this condition is met, it moves the div that we want to the right by 70px usingtranslateX(70px)
.
- This checks if the swipe direction is “Right” and if the
if (direction === "Left" && X <= SNAP_DISTANCE)
:- Similarly, this checks if the swipe direction is “Left” and if the
X
distance is less than or equal to the 70px (SNAP_DISTANCE
). If the condition is met, it moves the swipeable element to the left by 70px usingtranslateX(-70px)
.
- Similarly, this checks if the swipe direction is “Left” and if the
In summary, the function determines the final position of the swipeable element after the user action ends (If he lift his touch or the mouse moves out of div element ), and adjusting its position by 70px to the right or left based on the how far or narrow user swiped.
Using useRef and handlers on same element
const handlers = useSwipeable({ onSwiped: () => console.log('swiped') })
// setup ref for your usage
const myRef = useRef(null);
const refPassthrough = (el) => {
// call useSwipeables ref prop with el
handlers.ref(el);
// set the el to a ref you can access yourself
myRef.current = el;
}
return <div {...handlers} ref={refPassthrough} />