简体   繁体   中英

React JS swipe functionality not working as expected

I'm attempting to implement some swiping functionality into my app, but I'm currently struggling to get the correct behaviour I want.

I have a function which is called onTouchStart which saves the current touch objects' clientX and clientY position to the state, like so:

touchStart(e) {
    const touchObj = e.touches[0];
    this.setState({
        startX: touchObj.clientX,
        startY: touchObj.clientY,
    })
}

After the users begins to move their finger across the screen, I call another function onTouchMove , which saves the current clientX and clientY positions:

touchMove(e) {
    const touchObj = e.touches[0];
    this.setState({
        currentX: touchObj.clientX,
        currentY: touchObj.clientY,
    })
}

To then figure out whether a swipe was an up or down swipe, I call another function which takes the start positions and takes away the current positions. I also compare it against a threshold of 150 to make sure that it was an actual swipe, and not a long swipe (like a scroll). Here's what that looks like:

touchEnd(e) {
    this.setState({
        touchStarted: false,
    })
    if (Math.abs(this.state.startX - this.state.currentX) < this.state.threshold) {
        this.setState({
            direction: this.state.startY > this.state.currentY ? "top" : "bottom",
        })
        console.log(this.state.direction);
    }
}

The problem

This is detecting up and down swipes fine, but on the very first swipe a user does, the console.log returns the original state of none (as opposed to up or down ).

How do I ensure that the initial swipe is always set to the correct direction?

The problem continues further, whereby the user will have to swipe twice in the opposite direction for the state to be saved to the actual direction which is being swiped, like so:

up // none
up // up
down // up
down // down

Apologies if I've not articulated my problem too well. Here's a link to a CodePen where you can see the problem in further detail (you'll need a phone or an emulator to see the touch events).

Here's also a link to a post which I've been following to get this functionality working.

Any pointers would be highly appreciated. Thanks!

Here is the link to the fixed pen .

touchEnd(e) 
{
    var s = {
      touchStarted: false
    };

    if (Math.abs(this.state.startX - this.state.currentX) < this.state.threshold) 
    {
        s.direction = this.state.startY > this.state.currentY ? "top" : "bottom";
    }

    this.setState(s, () => console.log(this.state.direction))
}

The only "problem" was that you assumed that setState is synchronous and therefore checked state value immediately after its call, whereas it is not. If you want to check value of the state after setState has finished - use its second argument to pass callback function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM