Without a single NavigationContainer at the root, React Navigation has no scene graph to mount — screens render as disconnected components, deep links resolve to nothing, and the back button bubbles to the OS and closes the app. Users who tap a push notification or share-sheet link land on a blank route or a cold Home, destroying the user-experience contract the rest of the app depends on. Duplicated containers create competing state trees that silently drop navigation events.
Critical because a missing or duplicated NavigationContainer breaks every downstream routing, linking, and state-restoration feature app-wide.
Mount exactly one NavigationContainer at the app root and pass it a linking config. Put this in App.tsx so every screen is a descendant:
import { NavigationContainer } from '@react-navigation/native'
export default function App() {
return (
<NavigationContainer linking={linking}>
<RootNavigator />
</NavigationContainer>
)
}
Delete any secondary NavigationContainer instances — nested ones must be replaced by plain Navigator components.
ID: mobile-navigation-linking.navigation-structure.nav-init
Severity: critical
What to look for: Examine your root navigation setup. Look for NavigationContainer from @react-navigation/native wrapping your app. Check for linking configuration passed to NavigationContainer. In Expo projects, this is typically in App.tsx or a root navigation file.
Pass criteria: Count all NavigationContainer instances in the codebase. Exactly 1 NavigationContainer must be configured at the root of your app, with a ref or linking config. A linking config must be passed to NavigationContainer (either inline or as a separate object). The app structure follows React Navigation conventions. Report even on pass: "Found X NavigationContainer instances, linking config with Y prefixes."
Fail criteria: NavigationContainer is missing, duplicated (no more than 1 is allowed), or does not wrap the full app tree. Linking config is missing entirely. Do NOT pass when navigation is implemented with conditional renders or state-based screen switching instead of React Navigation or Expo Router.
Skip (N/A) when: Never — every React Native app needs navigation initialization.
Cross-reference: The Mobile Offline & Storage audit (mobile-offline-storage) checks state persistence that intersects with NavigationContainer's onStateChange handling.
Detail on fail: Describe what's wrong. Example: "NavigationContainer wraps only a subset of the app tree, not the root" or "No linking config passed to NavigationContainer"
Remediation: Your app's navigation must be initialized with NavigationContainer at the root. In App.tsx:
import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'
const Stack = createNativeStackNavigator()
export default function App() {
return (
<NavigationContainer linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
Define your linking config object (see deep linking checks below) and pass it to NavigationContainer.