react-native-gesture-handler
react-native-gesture-handler copied to clipboard
LongPress not working on web
Description
Not all LongPress callbacks are being called on web.
Platforms
- [ ] iOS
- [ ] Android
- [x] Web
Screenshots

Steps To Reproduce
Run the code below and press the red circle.
Expected behavior
For all these callbacks to be called:
onTouchesDownonBeginonStrartonTouchesUponEndonFinalize
Actual behavior
Only these callbacks are called:
onEndonFinalize
Snack or minimal code example
import { Platform, StyleSheet, Text } from 'react-native'
import {
Gesture,
GestureDetector,
GestureHandlerRootView,
} from 'react-native-gesture-handler'
import Animated, {
useAnimatedStyle,
useSharedValue,
} from 'react-native-reanimated'
export default function App() {
const isPressed = useSharedValue(false)
const onTouchesDownWasCalled = useSharedValue(false)
const onBeginWasCalled = useSharedValue(false)
const onStartWasCalled = useSharedValue(false)
const onTouchesUpWasCalled = useSharedValue(false)
const onEndWasCalled = useSharedValue(false)
const onFinalizeWasCalled = useSharedValue(false)
const longPressGesture = Gesture.LongPress()
.onTouchesDown(() => {
isPressed.value = true
onTouchesDownWasCalled.value = true
onBeginWasCalled.value = false
onStartWasCalled.value = false
onTouchesUpWasCalled.value = false
onEndWasCalled.value = false
onFinalizeWasCalled.value = false
})
.onBegin(() => {
onBeginWasCalled.value = true
})
.onStart(() => {
onStartWasCalled.value = true
})
.onTouchesUp(() => {
onTouchesUpWasCalled.value = true
})
.onEnd(() => {
onEndWasCalled.value = true
})
.onFinalize(() => {
isPressed.value = false
onFinalizeWasCalled.value = true
})
const onTouchesDownStyles = useAnimatedStyle(() => ({
opacity: onTouchesDownWasCalled.value ? 1 : 0,
}))
const onBeginStyles = useAnimatedStyle(() => ({
opacity: onBeginWasCalled.value ? 1 : 0,
}))
const onStartStyles = useAnimatedStyle(() => ({
opacity: onStartWasCalled.value ? 1 : 0,
}))
const onTouchesUpStyles = useAnimatedStyle(() => ({
opacity: onTouchesUpWasCalled.value ? 1 : 0,
}))
const onEndStyles = useAnimatedStyle(() => ({
opacity: onEndWasCalled.value ? 1 : 0,
}))
const onFinalizeStyles = useAnimatedStyle(() => ({
opacity: onFinalizeWasCalled.value ? 1 : 0,
}))
const ballAnimatedStyles = useAnimatedStyle(() => ({
backgroundColor: isPressed.value ? 'yellow' : 'red',
}))
return (
<GestureHandlerRootView style={styles.container}>
<Text style={styles.text}>
{Platform.OS === 'web' ? 'Web Version' : 'Native Version'}
</Text>
<Animated.View style={onTouchesDownStyles}>
<Text style={styles.text}>`onTouchesDown()` was called.</Text>
</Animated.View>
<Animated.View style={onBeginStyles}>
<Text style={styles.text}>`onBegin()` was called.</Text>
</Animated.View>
<Animated.View style={onStartStyles}>
<Text style={styles.text}>`onStart()` was called.</Text>
</Animated.View>
<Animated.View style={onTouchesUpStyles}>
<Text style={styles.text}>`onTouchesUp()` was called.</Text>
</Animated.View>
<Animated.View style={onEndStyles}>
<Text style={styles.text}>`onEnd()` was called.</Text>
</Animated.View>
<Animated.View style={onFinalizeStyles}>
<Text style={styles.text}>`onFinalize()` was called.</Text>
</Animated.View>
<GestureDetector gesture={longPressGesture}>
<Animated.View style={[styles.ball, ballAnimatedStyles]} />
</GestureDetector>
</GestureHandlerRootView>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
text: {
paddingBottom: 16,
fontSize: 16,
},
ball: {
width: 128,
height: 128,
borderRadius: 64,
},
})
Package versions
- React: 17.0.1
- React Native: 0.64.3
- React Native Gesture Handler: 2.2.1
- React Native Reanimated: 2.3.3
Hi! The linked PR should fix most of the issues. What's still not fixed are touch events (onTouches...), as that will require more research to see if implementing it using hammerjs is feasible.
Sounds good. Thanks for the update.
Also, I noticed that manual gestures currently aren't supported on web. I get this error message: Error: react-native-gesture-handler: ManualGestureHandler is not supported on web.
Is this related to the same issue with the touch events? Once the touch events are supported, will this make it possible to also support manual gestures on web?
That's right. Without touch events, manual gestures are pretty much useless since those are the only type of events they send without manually managing state, which can be done only inside touch event callbacks.
Okay, makes sense. Thanks for the reply.
Any updates on this issue/PR? Facing the same problem on web.
Hey! 👋
The issue doesn't seem to contain a minimal reproduction.
Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?
Hi 👋 This issue should be fixed in 2.6.1
Note that this change is available in new web implementation. To enable it, call enableExperimentalWebImplementation() in the root of your project.
@Warus15, thanks for letting me know. Sorry for the delay in my reply. I just got around to testing out the latest version (2.7.0) with enableExperimentalWebImplementation(true), and I can confirm that all callbacks are now being called on both native and web.
However, I just noticed that the order of the events is different between platforms.
On Android, the order is:
- onBegin
- onTouchesDown
- onStart
- onTouchesUp
- onEnd
- onFinalize
On iOS and web, the order is:
- onTouchesDown (called before onBegin)
- onBegin
- onStart
- onTouchesUp
- onEnd
- onFinalize
So it seems like the new web version is aligned with how iOS does it.
Because of this difference in order, I had to update my example code above to get it to work correctly across platforms since I was originally resetting the values in the onBegin callback, which I was incorrectly assuming would always be called first after testing it on Android (note: I was originally only testing it on Android and web, so I hadn't previously noticed the difference in behavior on iOS).
Given that this difference in order could lead to bugs, as it did in my example code above, do you think this difference should be fixed so that all platforms use the same order? If so, I can open a new issue about this. But I'll close this issue since this new issue is different than the original one.
Hi @elliotwaite 👋 Thanks for letting me know! I'm glad to hear that new implementation fixes this issue.
In web implementation order of events looks exactly how we wanted it to look like, so if one platform is inconsistent with the others, it would be nice if you could open new issue, so we can have a look at that.
Okay, sounds good, I created the new issue here: https://github.com/software-mansion/react-native-gesture-handler/issues/2263