Skip to content
useffect.sh
Book 30 min with a senior
UI

Expo Router

Expo’s file-based router: every file in the app directory becomes a screen, with deep links and typed routes out of the box.

Definition

Expo Router is Expo’s file-based navigation library: every file added to the app directory becomes a route, folders define nested navigators through _layout files, and the same tree serves Android, iOS, and the web. Every screen is automatically deep-linkable, routes can be statically typed, and native screens (stack, tabs) rely on React Native Screens. It replaces the manual navigator declarations and linking configuration that React Navigation alone required, the library Expo Router was historically built on. Since SDK 56, application code no longer imports the React Navigation packages directly, and since SDK 58 Expo Router builds the complete navigation state from the URL itself; the same release makes data loaders, SSR, middleware, and native tabs stable. You meet it as soon as a recent Expo project opens, since it is the default in the create-expo-app template.

In a real app

An Expo Router project is recognizable by its app/ (or src/app/) directory, a root _layout.tsx rendering Stack or Tabs, parenthesized groups such as (tabs) or (auth), and dynamic routes like [id].tsx. Navigation goes through Link with an href, or useRouter() (push, replace, back, dismissTo); useNavigation stays for navigator-specific APIs (events, options). Typed routes are enabled in app.json with experiments.typedRoutes and generate a .d.ts file that turns a link to a nonexistent route into a TypeScript error.

SDK 58 is a breaking change for projects that read navigation state or used the screen, params, and initial parameters to target a nested screen: those are now ordinary user parameters, and the migration guide recommends navigating to a complete href. initialRouteName is gone in favor of unstable_settings.anchor, and many compatibility APIs in expo-router/react-navigation were removed. On a project with a custom router or navigation.dispatch calls, budget for this migration.

What I check: that deep links are tested with npx uri-scheme open or xcrun simctl openurl, that stack screens are not remounted in a loop because a _layout renders conditionally on auth state (prefer Redirect or Stack.Protected), and that the app does not import @react-navigation/* alongside Expo Router.

Sources

All 35 glossary terms

One of these is blocking your app?

30 minutes with a senior to look at the problem in your code. Free.