You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Android] A quick tap on a button in a scroll view also presses React Native's Pressable around it #4626
On Android, a tap shorter than the tap timeout on a Touchable or RectButton inside a scroll view activates the button on the touch's UP: the scroll view defers its child's pressed state (ViewGroup.shouldDelayChildPressedState), and NativeViewGestureHandler activates on UP once the button reads pressed (NativeViewGestureHandler.kt#L159-L173). React Native's root view has handled that UP and ended its touch by then, so the cancel the activation sends reaches nothing: React Native logs Can't cancel already finished gesture. Is a child View trying to start a gesture from an UP/CANCEL event? (JSTouchDispatcher.kt#L244-L255), and a React Native Pressable around the scroll view presses as well as the button.
Held past the tap timeout, or with no scroll view between it and the Pressable, the gist's Touchable presses alone and nothing is logged.
Steps to reproduce
Render the component from the gist.
Tap the middle button, inside the scroll view inside the grey Pressable, with adb shell input tap <x> <y>: both [in scroll view in pressable] onPress and [pressable around scroll view] onPress are logged, and adb logcat -d | grep 'already finished gesture' shows the warning, which React Native logs under the tag unknown:ReactNative.
Tap the top button, inside a scroll view alone, the same way: it presses once and the warning is logged.
Tap the bottom button, inside a Pressable with no scroll view, the same way, or hold any of them for half a second: each presses alone and nothing is logged.
A link to a Gist, an Expo Snack or a link to a repository based on this template that reproduces the bug.
Have you tried using our Pressable component instead to see if that resolves the issue? If your setup requires a different approach, please provide more information on your specific use case 😅
I have now: with gesture-handler's Pressable around the scroll view in place of React Native's, a quick tap presses only the button. That leaves a React Native responder around the scroll view, React Native's Pressable here, which cancelsJSResponder is meant to cancel: the cancel still arrives after React Native has ended the touch, as the warning on every quick tap shows. gesture-handler's Pressable as the button behaves like Touchable, and gesture-handler's ScrollView in place of React Native's doesn't change it:
Quick tap on the button in a scroll view inside
Presses
Warnings
gesture-handler's Pressable, the button a Touchable
the button
1
gesture-handler's Pressable, the button gesture-handler's Pressable
the button
1
React Native's Pressable, the button gesture-handler's Pressable
both
1
React Native's Pressable, the scroll view gesture-handler's ScrollView
both
1
No app of mine depends on this; I ran into it while testing #4614. Measured on a release build of main at f4038e9 on an API 34 emulator with adb shell input tap; taps of 50 and 80 ms press both as well, and a 200 ms one only the button. I've also fixed the logcat command in the steps and in the gist: React Native logs the warning under unknown:ReactNative, so adb logcat -s ReactNative:W didn't show it.
Thanks for checking. Since our Pressable resolves this and there's no use case that requires React Native's responder around a scroll view with our buttons inside, I'm closing this. Let me know if we should reopen.
One more reading, on the 3.4.0 release, whose example app runs React Native 0.86.2: there the double press needs no scroll view. A quick tap on the gist's bottom Touchable, in the Pressable with no scroll view, presses both and logs the warning, because ReactViewGroup only stopped delaying its children's pressed state in 0.87 (ReactViewGroup.kt#L653 at v0.87.0). On React Native 0.86 and older, then, a gesture-handler button inside any view activates on UP after a quick tap, and a React Native Pressable around it presses too. Held for 400 ms, the bottom button presses alone, as on main.
I think it's worth reopening, because the scroll view turns out to be incidental: on iOS, React Native's Pressable around a gesture-handler Touchable presses together with it on every tap, quick or held, with no scroll view at all. That's the gist's bottom pair:
<Pressablestyle={styles.pressable}onPress={()=>console.log('[pressable around button] onPress')}><Touchablestyle={styles.button}onPress={()=>console.log('[in pressable] onPress')}/></Pressable>
On main at f4038e9, in a Release build on an iPhone 12 Pro Max with iOS 27.0.1, taps held for 0, 80, 250 and 400 ms each log both. On iOS a button never cancels React Native's touch: RNNativeViewHandler binds the button's UIControl through its control events and attaches no recognizer (RNNativeViewHandler.mm#L227-L273), while the responder is only cancelled from RNRootViewGestureRecognizer's canBePreventedByGestureRecognizer:, which takes a gesture-handler recognizer preventing the root one (RNRootViewGestureRecognizer.m#L41-L53). So cancelsJSResponder, which buttons take from the native gesture and which is on by default, has no effect on a button on iOS. On Android the same pair presses both on a quick tap with React Native 0.85 and 0.86, which 3.4 supports, as in my last comment.
Swapping in gesture-handler's Pressable still avoids it, so it comes down to whether cancelsJSResponder is meant to hold for buttons. If you'd rather track the iOS side as its own issue, I'll open one.
Thank you for the details. We are aware that the delay differs in RN 0.87. As for the second message, your repro still uses RN Pressable and you explicitly say that our Pressable resolves this problem, therefore we will keep this issue closed.
Activity
m-bert commentedon Oct 27, 2026
Hi @YevheniiKotyrlo! Thanks for reporting this.
Have you tried using our
Pressablecomponent instead to see if that resolves the issue? If your setup requires a different approach, please provide more information on your specific use case 😅YevheniiKotyrlo commentedon Oct 27, 2026
I have now: with gesture-handler's
Pressablearound the scroll view in place of React Native's, a quick tap presses only the button. That leaves a React Native responder around the scroll view, React Native'sPressablehere, whichcancelsJSResponderis meant to cancel: the cancel still arrives after React Native has ended the touch, as the warning on every quick tap shows. gesture-handler'sPressableas the button behaves likeTouchable, and gesture-handler'sScrollViewin place of React Native's doesn't change it:Pressable, the button aTouchablePressable, the button gesture-handler'sPressablePressable, the button gesture-handler'sPressablePressable, the scroll view gesture-handler'sScrollViewNo app of mine depends on this; I ran into it while testing #4614. Measured on a release build of
mainat f4038e9 on an API 34 emulator withadb shell input tap; taps of 50 and 80 ms press both as well, and a 200 ms one only the button. I've also fixed the logcat command in the steps and in the gist: React Native logs the warning underunknown:ReactNative, soadb logcat -s ReactNative:Wdidn't show it.m-bert commentedon Oct 27, 2026
Thanks for checking. Since our
Pressableresolves this and there's no use case that requires React Native's responder around a scroll view with our buttons inside, I'm closing this. Let me know if we should reopen.YevheniiKotyrlo commentedon Oct 27, 2026
One more reading, on the 3.4.0 release, whose example app runs React Native 0.86.2: there the double press needs no scroll view. A quick tap on the gist's bottom
Touchable, in thePressablewith no scroll view, presses both and logs the warning, becauseReactViewGrouponly stopped delaying its children's pressed state in 0.87 (ReactViewGroup.kt#L653 at v0.87.0). On React Native 0.86 and older, then, a gesture-handler button inside any view activates onUPafter a quick tap, and a React NativePressablearound it presses too. Held for 400 ms, the bottom button presses alone, as onmain.YevheniiKotyrlo commentedon Oct 27, 2026
I think it's worth reopening, because the scroll view turns out to be incidental: on iOS, React Native's
Pressablearound a gesture-handlerTouchablepresses together with it on every tap, quick or held, with no scroll view at all. That's the gist's bottom pair:On
mainat f4038e9, in a Release build on an iPhone 12 Pro Max with iOS 27.0.1, taps held for 0, 80, 250 and 400 ms each log both. On iOS a button never cancels React Native's touch:RNNativeViewHandlerbinds the button'sUIControlthrough its control events and attaches no recognizer (RNNativeViewHandler.mm#L227-L273), while the responder is only cancelled fromRNRootViewGestureRecognizer'scanBePreventedByGestureRecognizer:, which takes a gesture-handler recognizer preventing the root one (RNRootViewGestureRecognizer.m#L41-L53). SocancelsJSResponder, which buttons take from the native gesture and which is on by default, has no effect on a button on iOS. On Android the same pair presses both on a quick tap with React Native 0.85 and 0.86, which 3.4 supports, as in my last comment.Swapping in gesture-handler's
Pressablestill avoids it, so it comes down to whethercancelsJSResponderis meant to hold for buttons. If you'd rather track the iOS side as its own issue, I'll open one.m-bert commentedon Oct 28, 2026
Thank you for the details. We are aware that the delay differs in RN 0.87. As for the second message, your repro still uses RN
Pressableand you explicitly say that ourPressableresolves this problem, therefore we will keep this issue closed.