software-mansion / software-mansion/react-native-screens

[Android] navigate reordering a buried Screen (hosting a nested navigator) leaks a Screen that swallows all touches — #2466 regression on 4.26.2

Open
#4,382 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

platform:android repro-provided
Dominant language
TypeScript
Stars
3.7k
Forks
714
Avg merge
2d 23h
Merged PRs (30d)
71

Description

Description

On Android + New Architecture (Fabric), when @react-navigation navigate()
repeatedly reorders already-buried routes (RN7 navigate behavior — when a
getId match is found deeper in the stack, the route is reordered to the top
instead of a new one being pushed) and you then pop back down to a screen sitting
underneath the churn
, react-native-screens leaves a leaked Screen overlaying
the tree that swallows every touch
. The underlying screen is fully rendered and
visible, but Pressable/Touchable — and even a nested tab bar — stop responding.
Pan/scroll gestures still work (RNGH uses a separate touch path — the tell).

This reproduces #2150 / #2219, which were closed as fixed by #2466 (4.6.0)
but regress on 4.26.2 (current latest stable).

The topology matters — a flat stack of plain cards does not reproduce it.
The freeze needs a stack screen that hosts a nested navigator sitting
underneath the reorder churn:

Root Stack
├─ ProfileTab       ← initial/bottom screen; hosts a nested Bottom-Tab navigator
│   ├─ Collection tab   ← the surface that freezes
│   └─ About tab
├─ CollectionList   (card, getId = collectionList-<id>)  ┐ the two screens
└─ ProfileList      (card, getId = profileList-<id>)     ┘ you bounce between

Both outer navigator types reproduce it (toggle in the repro):

  • JS stack (@react-navigation/stack): underlying screen stays visible, all
    taps dead → the leaked Screen is transparent.
  • native-stack: underlying screen is fully covered by an opaque blank Screen.

View-hierarchy evidence: in the frozen state, adb shell uiautomator dump
shows ~6 stacked full-screen Screen FrameLayouts under the
NavigationContainer (all but one empty — leaked Screen containers from the
repeated reorders). The real content's buttons are still present and
clickable=true, yet receive no touches.

Workaround: dropping getId on Android for the churned screens (so navigate
pushes fresh instead of reordering) sidesteps it. detachInactiveScreens={false}
masks the freeze but has its own bug (#2978) breaking reanimated/gesture-handler.

Steps to reproduce
npm install
npx expo run:android    # New Architecture on by default
  1. Start on ProfileTab → its Collection tab. Tap the green TAP ME counter a
    couple of times — it increments (touch is alive).
  2. Tap RUN LOOP — it runs navigate("CollectionList",{id:1})
    navigate("ProfileList",{id:1}) 6× (first two push fresh, the rest reorder
    the buried duplicates), then popToTop() back to ProfileTab.
  3. Back on ProfileTab (content fully visible), tap TAP ME again, or tap the
    nested About tab.

Expected: counter increments; nested tab switches.
Actual: every tap is dead — counter frozen, nested tab bar unresponsive. Swipe
still works.

All the repro logic is a single App.tsx.

Snack or a link to a repository

https://github.com/LeCiel/rn-screens-navigate-reorder-touch-freeze

Screens version

4.26.2

React Native version

0.86.0

Platforms

Android

JavaScript runtime

Hermes

Workflow

Expo bare workflow (expo run:android)

Build type

Debug app & Metro bundler

Device

Android emulator

Device model

Pixel, API 36 (also seen on physical devices)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with App.tsx in the linked reproduction and run npm install followed by npx expo run:android on the New Architecture. Reproduce the navigate loop and pop back to ProfileTab, then use the described Android view-hierarchy evidence to investigate the leaked Screen containers. Done means taps and nested tab switching work after the loop while swipe gestures still work.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, react-native, typescript
Domain
mobile-dev
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.