Reputation: 3416
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);
}
}
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!
Upvotes: 0
Views: 2434
Reputation: 22352
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.
Upvotes: 2