mrkeyoor.com_
Tue 22 Sept 22:31 UTC
npmMobileupdated 22 Sept 2026

@react-navigation/native review

@react-navigation/native 7.3.17 is the state and integration layer under React Navigation. It provides the root container, focus lifecycle, themes, link-to-route conversion, refs, actions, and TypeScript helpers for React Native and web targets. It does not draw a stack, tab bar, or drawer; those come from separate navigator packages. Version 7 supports both JSX-based dynamic configuration and a static API that can infer route types. Our isolated Node checks could install the package and find its bundled declarations, but neither CommonJS require nor ESM import succeeded under Node 22.23.2. That is a practical warning that this package expects a React Native application environment rather than a standalone Node process.

Verdict

@react-navigation/native 7.3.17 took 18.2 seconds and 175 MB to install in our sandbox, where npm audit found 7 high-severity vulnerabilities and plain Node loading failed. Use it inside a configured React Native stack; Expo apps that want filesystem routes should begin with Expo Router.

We installed it

Lab card: what happened when we installed @react-navigation/nativeScreenshot of @react-navigation/native documentation
Install✓ · 18.2s222 packages on disk · 175 MB
ImportESM import fails · require() fails · CommonJS package with exports map
Browsern/acould not be bundled for the browser (Node-only code, most likely)
TypesTypeScript types bundled
Known vulns70 critical · 7 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does @react-navigation/native install cleanly?

Yes. In a fresh container with an empty cache, npm install @react-navigation/native finished in 18 seconds, leaving 222 packages and 175 MB on disk. npm audit reported 7 known vulnerabilities.

Can @react-navigation/native run in a browser?

Not directly: esbuild could not bundle it for the browser in our run, which normally means it depends on Node built-ins. Use it on the server, or find a browser-targeted alternative.

Does @react-navigation/native work with both ESM and CommonJS?

Neither plain import nor require succeeded in our sandbox, so it needs a bundler or extra setup.

Does @react-navigation/native include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

@react-navigation/native or expo-router: which should you use?

expo-router: Use it in Expo when files, layouts, and typed links should define routes over React Navigation. @react-navigation/native 7.3.17 took 18.2 seconds and 175 MB to install in our sandbox, where npm audit found 7 high-severity vulnerabilities and plain Node loading failed.

When should you not use @react-navigation/native?

You expect visible navigation after installing one package. native supplies infrastructure; stack, tabs, drawer, gestures, and screen components live elsewhere.

API stability4/5Version 7 retains NavigationContainer, route and navigation props, nested navigators, hooks, actions, themes, and linking while adding static configuration alongside the dynamic component API. That preserves normal 7.x applications and gives new projects another route-definition choice. Major boundaries still matter: the default repository branch documents the upcoming version 8 while the 7.x branch carries the installed stable line, so package versions, examples, and type patterns must stay on the same major.
Docs5/5The official site separates installation, static and dynamic configuration, each navigator, TypeScript, parameters, linking, persistence, themes, events, authentication flows, testing, web, and troubleshooting. Its getting-started page names native peers and rebuild steps rather than hiding them in a footnote. Version selection is the main trap: search results and the main GitHub branch can point at version 8 material while npm users are installing 7.3.17, so confirm the docs selector before copying an API.
Maintenance5/5npm currently serves 7.3.17, and GitHub records a repository push on 2026-08-19 plus same-day releases elsewhere in the monorepo. The project is unarchived, has 24,495 stars, and reports 842 open issues and pull requests across its many packages. Stable version 7 has a dedicated branch while version 8 work is visible on main. That activity is strong, although fixes may land in a sibling navigator package rather than `native` itself.
Ecosystem5/5npm counted 6,819,350 downloads in the latest completed week. This package anchors native stack, JavaScript stack, bottom and top tabs, drawers, elements, devtools, routers, React Native Web support, and Expo Router. The same breadth creates coordination cost: a working app commonly resolves several React Navigation packages plus Screens, Safe Area Context, Gesture Handler, or Reanimated, and their native versions must agree with the React Native or Expo release.

Use it if

  • A React Native application needs nested stacks, tabs, drawers, or modals assembled from the React Navigation package family.
  • One navigation state should coordinate app links, URL paths, themes, persistence, focus effects, and Android back behavior.
  • The team wants either component-driven route definitions or version 7 static configuration with inferred parameter types.
  • Your Expo, bare React Native, or React Native Web build can install and configure the required platform peers.
Skip it if

Setup reality

Our fresh install of @react-navigation/native 7.3.17 took 18.2 seconds in a Node 22 Bookworm sandbox. It left 222 packages and 175 MB on disk. The package itself declares 6 direct and 2 peer dependencies, is 872 KB unpacked, and bundles TypeScript declarations. npm audit reported 7 known vulnerabilities, all high severity. On Node.js 22.23.2, both require() and ESM import failed. esbuild also failed to make a browser bundle.

The install alone produces no navigator UI. Add react-native-screens, react-native-safe-area-context, and a navigator such as @react-navigation/native-stack. Expo projects should use expo install so native versions match the SDK. Bare iOS projects need CocoaPods installation; drawers or some tab and stack choices can also add Gesture Handler or Reanimated setup. Review the 7 high audit results in the resolved 222-package tree rather than assuming they belong to this 872 KB package.

Use exactly one ordinary NavigationContainer at the root of a dynamic setup. The version 7 static API instead returns a component through createStaticNavigation, which supplies its container. Keep route params small and serializable because state may be persisted or translated into a URL. If a deep link launched the app, do not overwrite it with saved initialState; web builds should normally treat the URL as the state source.

Linking still needs native and web configuration outside JavaScript: iOS associated domains, Android intent filters, URL schemes, hosted association files, and a rebuilt app. useFocusEffect needs a memoized callback plus cleanup because focus differs from mounting. A navigation ref must pass isReady() before use. Read version 7 docs or the 7.x branch, since the repository's default branch now describes the upcoming major version 8.

Patterns

Render a two-screen native stack create-native-stack

import { NavigationContainer } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'

const Stack = createNativeStackNavigator()

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  )
}

`@react-navigation/native-stack` is a separate install. The base native package only provides the surrounding container and state.

Declare routes with the version 7 static API use-static-navigation

import { createStaticNavigation } from '@react-navigation/native'
import { createNativeStackNavigator } from '@react-navigation/native-stack'

const RootStack = createNativeStackNavigator({
  screens: {
    Home: HomeScreen,
    Details: DetailsScreen,
  },
})

const Navigation = createStaticNavigation(RootStack)
export default function App() {
  return <Navigation />
}

The component returned by `createStaticNavigation` owns its root container. Adding another ordinary container creates the wrong hierarchy.

Pass a user identifier between screens navigate-with-params

function HomeScreen({ navigation }) {
  return (
    <Button
      title="Open profile"
      onPress={() => navigation.navigate('Profile', { userId: 'jane' })}
    />
  )
}

function ProfileScreen({ route }) {
  return <Text>User: {route.params.userId}</Text>
}

A small string survives persistence and URL conversion. Fetch the user in Profile instead of placing the whole object in navigation state.

Translate URLs into route parameters configure-deep-links

const linking = {
  prefixes: ['myapp://', 'https://app.example.com'],
  config: {
    screens: {
      Home: '',
      Profile: {
        path: 'users/:userId',
      },
      NotFound: '*',
    },
  },
}

<NavigationContainer linking={linking} fallback={<Loading />}>
  <RootNavigator />
</NavigationContainer>

This mapping does not register a platform link. iOS associations, Android intent filters, schemes, and a rebuilt binary still apply.

Override colors without dropping defaults set-theme

import { DarkTheme, NavigationContainer } from '@react-navigation/native'

const theme = {
  ...DarkTheme,
  colors: {
    ...DarkTheme.colors,
    primary: '#7dd3fc',
    background: '#0f172a',
    card: '#111827',
  },
}

<NavigationContainer theme={theme}>
  <RootNavigator />
</NavigationContainer>

Spread the original theme and its color map. Replacing `colors` outright omits values consumed by navigators and headers.

Cancel a focused-screen request on blur run-on-focus

import * as React from 'react'
import { useFocusEffect } from '@react-navigation/native'

function OrdersScreen() {
  useFocusEffect(
    React.useCallback(() => {
      const controller = new AbortController()
      loadOrders({ signal: controller.signal })
      return () => controller.abort()
    }, []),
  )
  return <OrdersList />
}

`useCallback` keeps the focus effect stable across renders. The returned abort handles blur and unmount cleanup.

Replay a blocked remove action prevent-leaving

import { Alert } from 'react-native'
import { usePreventRemove } from '@react-navigation/native'

usePreventRemove(hasUnsavedChanges, ({ data }) => {
  Alert.alert('Discard changes?', 'Your edits will be lost.', [
    { text: 'Stay', style: 'cancel' },
    {
      text: 'Discard',
      style: 'destructive',
      onPress: () => navigation.dispatch(data.action),
    },
  ])
})

Dispatch `data.action` after the user confirms. A fresh `goBack()` call may differ from the remove action that was intercepted.

Navigate outside React components navigate-outside-component

import { createNavigationContainerRef } from '@react-navigation/native'

export const navigationRef = createNavigationContainerRef()

export function openInbox() {
  if (navigationRef.isReady()) {
    navigationRef.navigate('Inbox')
  }
}

<NavigationContainer ref={navigationRef}>
  <RootNavigator />
</NavigationContainer>

The root ref is unavailable during startup, so guard it with `isReady()`. Screen code should continue to use the hook or prop.

Expose inferred static route types globally type-static-routes

import type { StaticParamList } from '@react-navigation/native'

type RootStackParamList = StaticParamList<typeof RootStack>

declare global {
  namespace ReactNavigation {
    interface RootParamList extends RootStackParamList {}
  }
}

`StaticParamList` reads names and parameter shapes from the navigator object. Dynamic JSX route definitions normally need a handwritten list.

Restore native navigation after restart persist-navigation-state

const [initialState, setInitialState] = React.useState()
const [ready, setReady] = React.useState(false)

React.useEffect(() => {
  AsyncStorage.getItem('NAVIGATION_STATE').then((value) => {
    if (value) setInitialState(JSON.parse(value))
    setReady(true)
  })
}, [])

if (!ready) return <Loading />
return (
  <NavigationContainer
    initialState={initialState}
    onStateChange={(state) =>
      AsyncStorage.setItem('NAVIGATION_STATE', JSON.stringify(state))
    }
  >
    <RootNavigator />
  </NavigationContainer>
)

Skip saved state when startup came from a link. On web, the address bar should normally remain the source of navigation truth.

Alternatives

PackageRegistryPick it when
expo-routernpmUse it in Expo when files, layouts, and typed links should define routes over React Navigation.
react-native-navigationnpmUse Wix's native-navigation model when platform-owned screens justify more native setup.
solitonpmUse it when the same screens must connect React Native navigation with a Next.js router.

More mobile guides

react-native · react-native-safe-area-context · expo · react-native-reanimated · react-native-svg · react-native-worklets · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.