fix(ios): keep a navigator mounted during hydration (no nav-context error)#111
Merged
Merged
Conversation
…rror) On native, the root layout's `!isReady` branch rendered a bare splash `View` with no expo-router navigator. expo-router requires a navigator on every render, so during the async hydration window (slow enough to actually paint on iOS, unlike web) navigation hooks threw "Couldn't find a navigation context." Replace the splash branch with a real loading route (`app/index.tsx`) and mount the `<Stack>` unconditionally. The initial `index` route is a no-fetch splash that `useProtectedRoute` forwards off once `isReady`, so the data screens (and their queries) still never mount against the pre-hydration default host — the request-storm fix from the original P0 change is preserved. Push notifications stay gated on `isReady`. Found via iOS Simulator testing (the error never surfaced on web because web hydrates before the splash paints). Verified on iPhone 17: the startup navigation-context error is gone (0 occurrences in a fresh Metro session). 1298 tests pass, typecheck + lint clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Found via iOS Simulator testing
Built and ran the app natively on the iPhone 17 simulator (
expo run:ios→ 0 errors). On launch, the dev LogBox showed a "Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'?" render error. It never surfaced on web because web hydrates before the splash paints.Root cause (my own P0 regression)
The original startup-request-storm fix (#103) gated the entire
<Stack>behindisReady, rendering a bare<View><ActivityIndicator/></View>splash while hydrating. expo-router requires a navigator on every render — so during the async hydration window (reading the persisted server URL + fetching auth config), a navigation hook fired with no navigator mounted → the error. iOS's slower hydration makes the splash actually paint, exposing it.Fix
app/index.tsx(no-fetch splash).<Stack>unconditionally;indexis the initial route.useProtectedRouteforwards offindexonceisReady(added anonIndexcase so a signed-in user lands on(tabs)).isReady.The request-storm fix is preserved: the data screens still only mount after the guard redirects post-hydration, so they never query the pre-hydration default host. The only early request is a single
get-session(harmless, retried at the correct host).Verification
Follow-up (separate, not in this PR)
Testing also surfaced a second, distinct native-only error: focusing the Connect screen's Server URL field throws the same "navigation context" error (our
Inputis a plainTextInputwith no nav hooks → a library-level interaction on TextInput focus; web connects fine). It needs isolating (likely react-navigation / react-native-screens) and is tracked separately.🤖 Generated with Claude Code