Minimal React Native app that contrasts:
- Bug (getId) —
ScreenB/ScreenCuse a constantgetId. Navigating to an identity that already exists reorders the sameroute.key. On native stack (react-native-screens) that reorder can leave a screen frozen (no touches). - Fixed (unique) — same screens, no
getId. AUniqueNavigationProviderwrapsnavigateso mid-stack duplicates are removed with an atomicresetthat appends a new route (new key).
Based on the handoff in ../unique-stack-navigation-handoff.md.
ScreenA → ScreenB → ScreenC
Each screen has Open next and Go back. ScreenC also has Open ScreenB again (trigger).
- Open the Bug (getId) tab.
- ScreenA → ScreenB → ScreenC.
- Tap Open ScreenB again (trigger).
- Watch the stack summary: ScreenB’s key tail should stay the same (reorder, not a new route).
- Tap Go back.
- Expected bug: ScreenC is frozen / unresponsive to touches.
- Open the Fixed (unique) tab.
- Same path: ScreenA → ScreenB → ScreenC → Open ScreenB again.
- Stack summary should show ScreenB with a new key tail; ScreenC is gone from history.
- Go back to ScreenA — screens stay interactive.
Requires Node ≥ 22.11.
cd rn-new-arch-unique-screen-repro
yarn
yarn start
# other terminal:
yarn ios
# or
yarn androidREC-20260717104210.mp4
| Path | Role |
|---|---|
src/navigation/uniqueScreenIds.ts |
Stack identity IDs config |
src/navigation/uniqueStackNavigate.ts |
Unique-stack navigate algorithm |
src/utils/routeHelpers.ts / stackHelpers.ts |
Param/identity + stack walk helpers |
src/contexts/UniqueNavigationContext.tsx |
Provider + useUniqueNavigation |
src/hooks/useAppNavigation.ts |
Wrapped navigate for screens |
src/hooks/useStackSummary.ts |
Stack name + key-tail summary |
src/navigation/navigators/ |
Root tabs, bug stack (getId), fixed stack |
src/screens/ |
ScreenA / ScreenB / ScreenC + shared DemoScreen UI |
Related: react-native-screens#2575, react-native-screens#2578.