How to Handle Swipe Event on React Carousel
Tags: react, javascript, css, html
Published: 2021-01-04 13:04:57

Previously we've created a Simple Carousel on React with a simple button to navigate to previous and next slide.

Now we will add a simple swipe event for touchscreen devices, this is particularly handy for mobile devices like smartphone to make it easier to navigate with 1 finger.

## Prequisites

Check my part 1 of this series to follow a step by step guide to make a simple react carousel, or you can pull directly from [my github repo](https://github.com/rakumairu/simple-react-carousel/tree/part-1).

## Handle Swipe Event

In Javascript you can add a swipe event handler using onTouchStart, onTouchMove, and onTouchEnd listener, we will only be using onTouchStart and onTouchMove for now.

### onTouchStart

onTouchStart is an event listener that will trigger a [touchstart event](https://developer.mozilla.org/en-US/docs/Web/API/Element/touchstart_event). In this application we will use onTouchStart to record where the user first touch the screen, this value will be used to measure if the user is just tapping the screen or actually want to initiate a swipe motion.

*Carousel.js* - add handler for onTouchStart
```jsx
// ...
const [touchPosition, setTouchPosition] = useState(null)
// ...
const handleTouchStart = (e) => {
    const touchDown = e.touches[0].clientX
    setTouchPosition(touchDown)
}
//...
```

*Carousel.js* - bind handleTouchStart to onTouchStart listener
```diff
  ...
- <div className="carousel-content-wrapper">
+ <div
+    className="carousel-content-wrapper"
+    onTouchStart={handleTouchStart}
+ >
  ...
```

Now every time the user touch the screen inside the Carousel Content Wrapper it will save the position to `touchPosition` state.

### onTouchMove

onTouchMove is an event listener that will trigger a [touchmove event](https://developer.mozilla.org/en-US/docs/Web/API/Document/touchmove_event) every time the user move their finger on the screen, it continuously check for current position of user's finger.

So what is the point for using this event listener you might say? By knowing the initial position of the user's finger and current position of user's finger we can measure the movement speed of user's finger, then we can determine if the user is currently swiping or not, and which direction of the swipe it is.

To determine the direction of the swipe, we will need a minimum speed of the finger's movement. In my experience, **5** and **-5** suits my application best *(negative value means the user swipe to the right)*, you may need to change the value around to suit your application best.

*Carousel.js* - add handler for onTouchMove
```jsx
// ...
const handleTouchMove = (e) => {
    const touchDown = touchPosition

    if(touchDown === null) {
        return
    }

    const currentTouch = e.touches[0].clientX
    const diff = touchDown - currentTouch

    if (diff > 5) {
        next()
    }

    if (diff < -5) {
        prev()
    }

    setTouchPosition(null)
}
// ...
```

*Carousel.js* - bind handleTouchMove to onTouchMove listener
```diff
  ...
  <div
     className="carousel-content-wrapper"
     onTouchStart={handleTouchStart}
+    onTouchMove={handleTouchMove}
  >
  ...
```

## And we are done!

![gif-1](https://dev-to-uploads.s3.amazonaws.com/i/vp0upnemg4gxpgxqf5kl.gif)

We've added swipe listener to handle navigating to previous and next slide. One more step that you might want to do is hide the control button on touchscreen devices, there are use cases where we still want to display the button, that's why add this as and extra step.

## Hide Control Button on Touchscreen Device

To detect if the device utilize touchscreen or not using only css, you can read this [article](https://medium.com/@ferie/detect-a-touch-device-with-only-css-9f8e30fa1134) by ferie that explains the css selector that able to detect touchscreen and pointer.

We basically want to add `display: none;` to `.left-arrow` and `.right-arrow` class.

*Carousel.css*
```css
/* ... */
@media (hover: none) and (pointer: coarse) {
    .left-arrow, .right-arrow {
        display: none;
    }
}
/* ... */
```

And that's it!
You can check the final full code on [my Github](https://github.com/rakumairu/simple-react-carousel/tree/part-2).

If you have any suggestions on how to handle swipe event better, you can tell me down on the comments! I would love to hear your ideas.

The next post will be about showing multiple item at once in the Carousel.