Repository navigation
fix: hide a sheet hosted in a tab screen when an enclosing stack pushes a screen - #910
Merged
lodev09 merged 5 commits intoOct 13, 2026
Conversation
…es a screen A sheet whose nearest react-native-screens screen is a bottom-tab screen stayed presented when the stack enclosing the tabs pushed a screen, so the pushed screen ended up behind the sheet. iOS: the presenter was only compared against the top of its nearest navigation controller, which for a tab is the tabs container where the active tab is always on top. Also walk the enclosing navigation controllers. Android: react-native-screens dispatches lifecycle events for stack screens only, so a tab screen never receives them. Also listen on the enclosing screens, and let stacked sheets inherit them from their parent. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@IjzerenHein is attempting to deploy a commit to the lodev09 Team on Vercel. A member of the Team first needs to authorize it. |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Listening to the enclosing screens meant any of them reappearing restored the sheet. A sheet whose own screen was still covered by a push inside a nested stack came back on top of that screen after the enclosing stack pushed and popped. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
lodev09
approved these changes
Oct 13, 2026
lodev09
left a comment
Owner
There was a problem hiding this comment.
Thanks @IjzerenHein! Verified on the iOS 27 simulator and an Android emulator, A/B against main, including tabs as the root stack's initial route (the repro pushes them):
- Sheet in a tab, and in a stack inside a tab, with the enclosing stack pushing and popping: hidden, then restored (on
mainit stays over the pushed screen) - Nested stack, inner push then outer push and pop: stays hidden, comes back with its own screen
- Stacked sheets in a tab (Android): both hide and come back
- Back swipe cancelled, then committed (iOS): stays hidden, restored on commit
Merged main and resolved the changelog conflict.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
Author
|
Awesome, thanks for merging @lodev09 ❤️ |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A sheet is hidden when its presenter screen is covered by a push and restored when the screen comes back. That only works when the sheet's nearest
react-native-screensscreen is itself a stack screen. When the sheet lives in a bottom-tab screen and the native stack enclosing the tabs pushes a screen, the sheet stays presented and the pushed screen ends up behind it.The two platforms miss this for different reasons:
shouldDismissForScreenTag:compares the presenter againstnavigationController.topViewController. For a tab screen that navigation controller is the tabs container (RNSContainerNavigationController), where the active tab is always on top, so the check returnsNO. The enclosing stack screen'stopWillDisappeargoes through the parent branch, which only handles a nested stack being removed. The fix also walks the enclosing navigation controllers and dismisses when the presenter is no longer under one of their top view controllers.react-native-screensonly dispatches lifecycle events forScreenStackFragments, so a tab screen never receivestopWillDisappear/topWillAppear, and the observer only listens for the nearest screen's tag. The fix also records the enclosing screens' tags and reacts to their events. Stacked sheets inherit them from their parent, like they already inherit the presenter tag. Only the screen that hid the sheet brings it back, so an enclosing screen reappearing doesn't reveal a sheet whose own screen is still covered inside it.With the fix the sheet is hidden for the push and comes back on return with its content state intact, same as a sheet hosted directly in a stack screen.
The same change also covers two neighbouring cases:
Type of Change
Test Plan
E2E in the Expo example with the repro screens added in this PR (
yarn expo open repro/tabs), on the iOS 26.5 simulator and an Android API 35 emulator, A/B against the parent commit:Stacked sheets in a tab hide and come back together on Android.
The tab case was first found and fixed in our production app (3.11.12 with this change applied as a patch, minus the Android restore guard,
react-native-screens4.24.0,@react-navigation/bottom-tabs7 inside a native stack), on both platforms.Web does not hide sheets for navigation, so it is not affected.
clang-formatandktlintreport no changes for the touched native files.yarn typecheckpasses, and ESLint and Prettier are clean for the repro screens.Two things I noticed while testing that this PR doesn't change, so I left them alone:
react-native-screensnever dispatches its firsttopWillAppear, and gatestopWillDisappearon it.Screenshots / Videos
Can add before/after captures if useful.
Checklist
🤖 Generated with Claude Code