Skip to content

GestureDetector gestures dead on eagerly-mounted, non-detaching tabs on iOS — two deterministic variants; one unrecoverable #4477

Description

@muhasabahhub

Description

With a bottom-tab navigator using detachInactiveScreens={false} and screenOptions={{ lazy: false }}, a GestureDetector (Gesture.Exclusive(Pan(activeOffsetX ±2), Tap)) on a tab screen fails on iOS in two deterministic ways, depending on whether the tab was focused at cold start:

Variant A — tab mounted unfocused at cold start, then switched to: Gesture.Tap never fires (no onBegin), while the Gesture.Pan in the same Exclusive works. The dead Tap persists for the entire session — pressing other RN views, tab switches, and stack pushes do not recover it. Reproduced 3/3 cold sessions; revived 0/3.

Variant B — tab focused at cold start, switched away and back: both Tap and Pan are dead. Pressing a plain RN on the same screen revives both immediately. Reproduced 3/3; revived 3/3.

A plain RN

beside the detector works at all times in both variants, so touch delivery into React is healthy — the failure is in the gesture-handler path. Removing either detachInactiveScreens={false} or lazy: false makes both variants unreproducible. Not observed on Android.

Looks related to #2920 (iOS, GestureDetector "loses connection"; fixed for the pushed-screen case in #2925) — but this reproduces on gesture-handler 2.32 with kept-alive tab roots, and Variant A is not recoverable by touching elsewhere, only by remounting the detector.

Steps to reproduce

Requires: iOS, tab navigator with detachInactiveScreens={false} and screenOptions={{ lazy: false }}.

Variant A (repo ships this config):

  1. npm install && npx expo start, open in Expo Go on a physical iPhone.
  2. Cold start — app opens on the "Other" tab. Touch nothing.
  3. Switch to the "Counter" tab.
  4. Tap the blue GestureDetector box → taps stays 0 (BUG). Drag it → pans increments.
  5. Press the plain RN Button → works, but taps stays dead for the whole session (3/3 dead, 0/3 revived).

Variant B (one-line change: initialRouteName="CounterTab"):

  1. Cold start — app opens on the "Counter" tab.
  2. Switch to "Other", then back to "Counter".
  3. Tap and drag the box → both taps and pans stay 0 (BUG).
  4. Press the plain RN Button → both revive immediately and work thereafter (3/3 dead, 3/3 revived).

Expected: gestures fire from the first touch in both variants.

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

https://github.com/muhasabahhub/gh-taproot

Gesture Handler version

2.32.0

React Native version

0.86.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Using Expo Go

Architecture

New Architecture (Fabric)

Build type

Debug mode

Device

Real device

Device model

IPhone 15 - iOS 26.6.1

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

    Platform: 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