Skip to content

fix(iOS): avoid lazy tab flash on iOS 27 - #564

Draft
thiagobrez wants to merge 1 commit into
mainfrom
codex/fix-547-ios27-lazy-flash
Draft

fix(iOS): avoid lazy tab flash on iOS 27#564
thiagobrez wants to merge 1 commit into
mainfrom
codex/fix-547-ios27-lazy-flash

Conversation

@thiagobrez

@thiagobrez thiagobrez commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Fixes #547.

PR Description

iOS 27's shouldSelectTab delegate switches the native TabView immediately. On a lazy route's first activation, React had not mounted that scene yet; TabView also 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 — passed
  • yarn lint — passed (two existing React Native deep-import warnings)
  • yarn typecheck — passed
  • focused isRouteLoaded Jest regression suite — 3 passed
  • yarn build:android — passed
  • iOS 27 Debug simulator xcodebuild — passed
  • aggregate yarn test — existing repository runner stops because @bottom-tabs/react-navigation contains no tests; the new focused suite passes independently

Device verification used agent-device 0.20.10 with Xcode 27.0 (27A5228h), React Native 0.81.4/Hermes/New Architecture, and an iPhone 17 Pro simulator:

  1. Reproduced before the change on iOS 27.0 runtime 24A5390f with the example app's default-lazy Native > Lazy Tabs flow.
  2. Recorded the first Contacts activation at 50 fps; the sampled frames contain a fully white content frame.
  3. Rebuilt after the fix and repeated the exact activation at 75 fps; Article remains visible until Contacts is mounted, with no empty frame.
  4. Repeated with a lazy screen whose permanent background is #1E2D2F; no white or empty frame appears.
  5. Repeated the first-load Contacts path on an iOS 26.5 simulator (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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

White flash when lazily loading a tab on iOS 27

1 participant