Swipe Effect in React Js

I'm trying to create a swipe event using React. I do not want to use any external component or jquery.

The css is something like :

.outter{
  position:relative;
  width: 100%;
  height: 150px;
  background-color: blue;
}

.inner{
  position: absolute;
  width: 1000%; 
  left: 50px;
}
.child{
  float: left;
  margin-right: 15px;
}

In the react component I'm trying to do something like :

class Test extends React.Component {
    constructor(props){
    super(props);

    this.state = {
        left: 0
    }
  }

  handleSwipe(){
    this.setState({left: -350})
  }

  render(){
    return(
        <div className="outter">
            <div className="inner" style={{left: this.state.left}} onSwipe={this.handleSwipe.bind(this)}>
                 <div className="child"><img src="" /></div>
                 <div className="child"><img src="" /></div>
                 <div className="child"><img src="" /></div>
                 <div className="child"><img src="" /></div>
            </div>
      </div>
    )
  }
}

React.render(<Test />, document.getElementById('container'));

How can I recognize swipe event?

If I in my example instead of onSwipe add onClick it works, but how can I make the swipe effect?

Here is jsfiddle.

1

4 Answers

You can add onTouch event handlers to your React components:

onTouchStart={touchStartEvent => this.handleTouchStart(touchStartEvent)}
onTouchMove={touchMoveEvent => this.handleTouchMove(touchMoveEvent)}
onTouchEnd={() => this.handleTouchEnd()}

You may also want to add event handlers for mouse events for cross-platform compatibility:

onMouseDown={mouseDownEvent => this.handleMouseDown(mouseDownEvent)}
onMouseMove={mouseMoveEvent => this.handleMouseMove(mouseMoveEvent)}
onMouseUp={() => this.handleMouseUp()}
onMouseLeave={() => this.handleMouseLeave()}

You have the right idea for updating the left property of state in an event handler, but if you want the swiping functionality to feel natural you'll need to track the position of the pointer (be it a mouse or a touch) by updating left using the event's clientX property.

To do this, you'll need to store the position of the first touch and set left equal to the change in the touch's location. For added realism, you can also keep track of the touch's velocity and continue animating the component after the touch is finished.

Here's a quick-n-dirty Codepen I made for swiping to remove items from a list:

6

I used good solution above as a base for build what I was needed. Maybe somebody need something like this. Idea was to move my custom slider left and right on swipe effect. If you want it to be more sensitive adjust 150 to 75.

const [touchStart, setTouchStart] = React.useState(0);
const [touchEnd, setTouchEnd] = React.useState(0);

function handleTouchStart(e) {
    setTouchStart(e.targetTouches[0].clientX);
}

function handleTouchMove(e) {
    setTouchEnd(e.targetTouches[0].clientX);
}

function handleTouchEnd() {
    if (touchStart - touchEnd > 150) {
        // do your stuff here for left swipe
        moveSliderRight();
    }

    if (touchStart - touchEnd < -150) {
        // do your stuff here for right swipe
        moveSliderLeft();
    }
}
0

Might be for someone my solution will be also useful:


export const useSwipe = ({left, right, up, down}: {left?: () => void; right?: () => void; up?: () => void; down?: () => void;}) => {
  const touchCoordsRef = useRef({touchStart: {x: 0, y: 0, time: Date.now()}});
  const fnsRef = useRef({up, down, left, right});
  fnsRef.current = {
    up,
    left,
    down,
    right,
  };
  useEffect(() => {
    const handleTouchStart = (e: TouchEvent) => {
      touchCoordsRef.current.touchStart.x = e.targetTouches[0].clientX;
      touchCoordsRef.current.touchStart.y = e.targetTouches[0].clientY;
      touchCoordsRef.current.touchStart.time = Date.now();
    };
    const handleTouchEnd = (e: TouchEvent) => {
      const threshold = 150;
      const swipeSpeed = 1; // sec;
      const touchEndX = e.changedTouches[0].clientX;
      const touchEndY = e.changedTouches[0].clientY;
      const touchStartX = touchCoordsRef.current.touchStart.x;
      const touchStartY = touchCoordsRef.current.touchStart.y;
      const elapsedTime = (Date.now() - touchCoordsRef.current.touchStart.time) / 1000;
      if(elapsedTime > swipeSpeed) {
        return;
      }
      const xDistance = touchStartX - touchEndX;
      const yDistance = touchStartY - touchEndY;

      if(Math.abs(xDistance) < threshold && Math.abs(yDistance) < threshold) {
        return;
      }

      if(Math.abs(xDistance) >= Math.abs(yDistance)) {
        xDistance > 0 ? fnsRef.current.right?.() : fnsRef.current.left?.();
      } else {
        yDistance > 0 ? fnsRef.current.down?.() : fnsRef.current.up?.();
      }
    };
    window.addEventListener('touchstart', handleTouchStart);
    window.addEventListener('touchend', handleTouchEnd);
    return () => {
      window.removeEventListener('touchstart', handleTouchStart);
      window.removeEventListener('touchend', handleTouchEnd);
    };
  });
};

Just found a DOM event that could be useful. Add .ontouchend to your HTML tag to detect any swipe event originating from that tag.

- ref

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling

James H. Sterling

Environmental Science & Climate Journalist

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.

Share this article
Twitter Facebook Pinterest