Skip to content

[iOS ≤ 18] RN Pressable inside RNGH FlatList/ScrollView never fires onPress when a Reanimated :active pseudo-selector is attached (touch is cancelled) #4496

Description

@roy-ling

Description

A react-native Pressable rendered inside a react-native-gesture-handler FlatList (or ScrollView) stops firing onPress on iOS 17 and iOS 18 as soon as the pressable carries a Reanimated CSS :active pseudo-selector style. onPressIn and onPressOut fire, onTouchCancel fires, onPress never does. The same tree works on iOS 26, works with react-native's own FlatList/ScrollView, and works without the :active style.

Reanimated implements :active on iOS by attaching a UILongPressGestureRecognizer with minimumPressDuration = 0 and cancelsTouchesInView = NO to the view (REAPseudoSelectorObserver.mm). RNGH's RNNativeViewHandler forces the wrapped UIScrollView to delaysContentTouches = YES (apple/Handlers/RNNativeViewHandler.mm), whereas RN's scroll view keeps it NO. On iOS ≤ 18 that combination results in RCTSurfaceTouchHandler receiving touchesCancelled:, so RN's Pressability terminates the press and drops onPress. iOS 26 no longer cancels the touch.

Results from the minimal repro below (same result for a still tap and a tap with a few points of finger movement):

Variant iOS 26.5 sim iOS 18.6 sim iOS 17.5 sim
RNGH FlatList / RN Pressable with :active onPress fires no onPress, onTouchCancel fires no onPress, onTouchCancel fires
RNGH FlatList / RN Pressable, :active on a child Animated.View fires no onPress no onPress
RNGH FlatList with canCancelContentTouches={false} / RN Pressable :active fires no onPress no onPress
RNGH FlatList / RNGH Pressable with :active fires fires (touch still cancelled, ignored) fires
RNGH FlatList / RN Pressable without :active fires fires fires
RN FlatList or RN ScrollView / RN Pressable with :active fires fires fires
No list / RN Pressable with :active fires fires fires

I am filing this here because the RNGH scroll wrapper is the ingredient that makes RN's touch cancellable;

Expected behaviour

onPress fires for an RN Pressable inside an RNGH FlatList regardless of the Reanimated :active style, as it does on iOS 26 and inside RN's own FlatList.

Actual behaviour

On iOS 17 and 18 the touch is cancelled once the :active recogniser is attached: onPressIn → onTouchCancel → onPressOut, no onPress.

Steps to reproduce

  1. Create a fresh RN app (New Architecture) with react-native-gesture-handler and react-native-reanimated, wrap the root in GestureHandlerRootView.
  2. Replace App.tsx with the snippet below.
  3. Run on an iOS 17 or 18 simulator (iPhone 15 / iOS 17.5 and iPhone 16 / iOS 18.6 used here).
  4. Tap a card in row 1. Observe in 1 / press 0 / out 1 / cancel 1.
  5. Tap a card in row 2 (RNGH Pressable) or row 3 (no :active). Observe press 1.
  6. Repeat on an iOS 26 simulator: every row reaches press 1.

A link to a Gist, an Expo Snack or a link to a repository based on this template that reproduces the bug.

https://gist.github.com/roy-ling/c17556168855ea787011729f6284d907

Gesture Handler version

2.31.2

React Native version

0.83.10

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Using Expo Prebuild or an Expo development build

Architecture

New Architecture (Fabric)

Build type

None

Device

Real device

Device model

iPhone 13 Pro on iOS 18.7

Acknowledgements

Yes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Close when staleThe issue will be closed automatically if it remains inactivePlatform: iOSThis issue is specific to iOS

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions