fix(Android): don't run header update for a screen detached from its stack - #4498
Open
nsingh-ut wants to merge 1 commit into
Open
fix(Android): don't run header update for a screen detached from its stack#4498nsingh-ut wants to merge 1 commit into
nsingh-ut wants to merge 1 commit into
Conversation
…stack `ScreenStackHeaderConfig.onUpdate()` computed `isTop` as `stack == null || stack.topScreen == parent`, so a null `screenStack` was treated as "is top" and execution continued. It then reached `ScreenStackFragment.canNavigateBack()`, which does `check(container is ScreenStack)` and throws on exactly the state the first guard allowed through. A screen detached from its stack while its header config is still attached therefore crashed with `IllegalStateException: ScreenStackFragment added into a non-stack container`. Return early when there is no stack, so both checks agree. Closes software-mansion#4429
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.
Description
ScreenStackHeaderConfig.onUpdate()andScreenStackFragment.canNavigateBack()disagree about the same condition, so a screen detached from its stack while its header config is still attached crashes the app.onUpdate()computes:A null
screenStackis treated as "is top", so execution continues. Further down it reaches:newActionBar.setDisplayHomeAsUpEnabled( screenFragment?.canNavigateBack() == true && !isBackButtonHidden, )and
canNavigateBack()asserts on exactly the state the first guard let through:Both read the same
Screen.containerfield. If it is not aScreenStack, the permissive check passes and the strict one throws.This is what users hit in #4429: an intermittent
IllegalStateExceptionon Android/Fabric during ordinary navigation, when a props update or an attach reaches a header config after its screen has left the stack.Closes #4429.
Changes
legacy/ScreenStackHeaderConfig.onUpdate()returns early whenscreenStackis null, instead of treating it as "is top".Scoped to the legacy implementation deliberately: the newer
stack/code passescanNavigateBacktoStackScreenFragmentas a constructor value and has no equivalent assertion, so it is unaffected.Test plan
The crash is a race and does not reproduce on demand, so I made the transient state permanent for one screen and did an A/B.
In
onUpdate(), before the guard, I detached one screen from its stack. That is the same field both accessors read, so it reproduces the real end state:Built a debug app (RN 0.86, Expo 57, Fabric,
react-native-screens4.25.2, Android 16 emulator) and navigated to that screen.1. Without this change: crashes every time.
This matches the trace in #4429, which arrives via
onAfterUpdateTransactioninstead ofonAttachedToWindow. Both callonUpdate(), so the guard covers both entry points.2. With this change, detach still forced: no crash, screen renders. Its header is skipped, which is correct, since a screen with no stack has no stack header to configure.
3. With this change, detach removed: normal behaviour, title and back button render as before.
Checklist