fix(iOS): avoid lazy tab flash on iOS 27 - #564
Draft
thiagobrez wants to merge 1 commit into
Draft
Conversation
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.
Fixes #547.
PR Description
iOS 27's
shouldSelectTabdelegate switches the nativeTabViewimmediately. On a lazy route's first activation, React had not mounted that scene yet;TabViewalso rendered its empty placeholder for the newly focused route's first render. The native transition therefore exposed an empty white content frame.This PR sends each route's internal loaded state to iOS. On iOS 27 only, native selection of an as-yet-unloaded lazy tab is declined for that event, leaving the current scene visible while the existing controlled selection callback runs. The newly focused route is materialized in that same React render, and the subsequent controlled update selects it. Already-loaded and eager tabs retain immediate native selection.
This is deliberately scoped to iOS 27's delegate path: iOS 26 and earlier keep their existing selection behavior, Android ignores the internal field, custom content backgrounds remain visible, and default lazy semantics are preserved. There are no delays, eager rendering, masks, or public API changes. A patch changeset is included.
How to test?
Automated/local validation:
yarn build— passedyarn lint— passed (two existing React Native deep-import warnings)yarn typecheck— passedisRouteLoadedJest regression suite — 3 passedyarn build:android— passedxcodebuild— passedyarn test— existing repository runner stops because@bottom-tabs/react-navigationcontains no tests; the new focused suite passes independentlyDevice verification used
agent-device0.20.10 with Xcode 27.0 (27A5228h), React Native 0.81.4/Hermes/New Architecture, and an iPhone 17 Pro simulator:24A5390fwith the example app's default-lazy Native > Lazy Tabs flow.#1E2D2F; no white or empty frame appears.23F77); the scene loads normally.The complete environment, steps, explicit accessibility assertions, logs, and artifact index are in
artifacts/issue-547/README.md.Screenshots and videos
Before:
After:
Required CI status: all nine CI and CodeQL checks passed, including lint, SwiftLint, library, Android, and iOS builds.