Expo Router vs React Navigation in 2026: Which to Use and Why
Expo Router vs React Navigation in 2026: file-based routes vs config, deep links, web URLs, native tabs, what changed in SDK 56, and which to pick.
Full-Stack, Mobile & AI Engineer
Navigation is the skeleton of a mobile app: every screen hangs off it, every deep link lands in it, and changing it later touches everything. For years, React Navigation was the obvious choice. Then Expo Router arrived with file-based routing, automatic deep links and web URLs, and the question became which one to pick, and whether to move.
In 2026 the answer has also shifted underneath: with Expo SDK 56, Expo Router stopped depending on React Navigation and forked the parts it builds on. This guide compares Expo Router and React Navigation as they stand today, explains what that change means, and gives a clear recommendation for new and existing apps.
Key takeaways
- Expo Router uses your file structure as your navigation: every file in
app/is a route, with deep links and web URLs automatically. - React Navigation uses configuration in code, and remains a solid, flexible choice, especially for bare and brownfield apps.
- Since SDK 56, Expo Router no longer depends on React Navigation; most direct
@react-navigation/*imports don't work withexpo-router, and Expo provides a codemod. - For new Expo apps, Expo Router is the default and the better choice.
- For existing React Navigation apps, migrate only when you gain something (web, deep links, consistency), not because of fashion.
How each one works
Expo Router maps files to routes:
app/
_layout.tsx // root stack
(tabs)/
_layout.tsx // tab navigator
index.tsx // "/" home tab
bookings.tsx // "/bookings"
class/
[id].tsx // "/class/123"
settings.tsx // "/settings"Each layout file decides how its children are shown (stack, tabs, modal). Links use URLs: <Link href="/class/123">. Every route is automatically deep-linkable and, on the web, has a real URL.
React Navigation is configured in code: you create stack and tab navigators, register screens, and navigate by screen name. Version 7 added a static configuration API that brings type safety and automatic linking closer to what file-based routing offers.
Expo Router vs React Navigation at a glance
| Expo Router | React Navigation | |
|---|---|---|
| Route definition | Files and folders in app/ | Navigators configured in code |
| Deep links | Automatic for every route | Configured (simpler with the static API) |
| Web URLs | Built in, with static or server rendering | Possible, more setup |
| Typed routes | Generated from the file system | Through TypeScript configuration |
| Native tabs | Native system tabs, including Liquid Glass on iOS 26 | Through native-backed navigators |
| API routes | Yes (server endpoints alongside routes) | No |
| Best for | New Expo apps, apps with web, deep-link-heavy apps | Bare and brownfield apps, very custom navigation |
What changed in SDK 56
Expo Router was originally built on top of React Navigation. In SDK 56, Expo forked the parts of React Navigation that Expo Router builds around, so the router no longer depends on the React Navigation packages. The practical effects:
- Code importing directly from
@react-navigation/*inside an Expo Router app may stop working out of the box. - Expo provides a codemod (
npx expo-codemod sdk-56-expo-router-react-navigation-replace) and a migration guide for the manual steps. - React Navigation itself continues as an independent library, and Expo offers a template for projects that prefer it.
If you upgrade an Expo Router app to SDK 56 or later, run the codemod first and then fix any remaining imports.
Common pitfalls with file-based routing
File-based routing is simple until a few patterns bite:
- Auth gating. Don't scatter redirects across screens. Protect groups of routes in their layout (for example with protected stacks or a redirect in the group's
_layout.tsx), so signed-out users can't reach them by deep link either. - Groups versus paths. Folders in parentheses, like
(tabs), organise routes without adding to the URL. Mixing them up creates confusing paths and duplicate screens. - Heavy layouts. Layout files render around many screens. Keep data fetching and expensive work in screens, not layouts, or every navigation pays for it.
- Params as strings. Route params arrive as strings; parse and validate them (for example with Zod) before using them as numbers or IDs.
- Renaming files is renaming URLs. Moving a file changes its route, which can break shared links and notifications. Treat renames like API changes.
Expo Router how-tos people search for
Reading params. A route like app/bookings/[id].tsx reads its params with a hook:
const { id } = useLocalSearchParams<{ id: string }>();Setting the anchor screen. To make sure deep-linked screens can navigate back to a sensible root, set an anchor in the layout. It replaces the deprecated initialRouteName:
export const unstable_settings = { anchor: "index" };Tabs. A (tabs) group with a _layout.tsx that renders <Tabs /> gives you a tab bar whose screens are the files in that folder.
Sheets and modals. Set presentation in a stack screen's options (for example "modal" or "formSheet") to present a route as a modal or sheet.
Replacing without animation. router.replace("/home") swaps the current screen; set the target screen's animation option to "none" when you don't want a transition, for example after sign-in.
Styling. NativeWind and other styling libraries work normally inside Expo Router screens; routing and styling are independent.
When Expo Router isn't working
- A route doesn't exist: check the file sits inside the app directory, has a default export, and isn't hidden by a group name you didn't intend.
- Navigation goes to the wrong screen: look for two files resolving to the same path, often a group and a folder with the same name.
- Back goes somewhere odd after a deep link: set an anchor in the parent layout.
- Types complain about routes: restart the dev server so typed routes regenerate.
When to choose Expo Router
- You're starting a new Expo app.
- You want deep links, universal links and shareable URLs without maintaining a linking config.
- You plan a web version of the app.
- You like the predictability of "the file is the route" across a growing team.
When to stay with (or choose) React Navigation
- Your app is bare React Native, or React Native embedded in a native app.
- You have a large, working navigation setup and no reason to change it.
- Your navigation is unusual enough that configuration in code is clearer than files.
From the field: I've shipped apps with Expo Router navigation and with React Navigation, on both Expo and bare workflows. For new Expo apps I'd choose Expo Router without hesitation; for an existing app with a stable React Navigation setup, I'd only migrate alongside a reason like adding a web version or overhauling deep links.
Migrating from React Navigation to Expo Router
If you decide to move:
- Map your navigators to layouts: each stack or tab navigator becomes a folder with a
_layout.tsx. - Move screens into route files, and turn route params into dynamic segments (
[id].tsx). - Replace
navigation.navigatecalls withrouter.pushand<Link>using paths. - Remove the manual linking config and test every deep link and universal link.
- Ship incrementally if the app is large: keep a working build at every step and test on both platforms.
FAQ
Is Expo Router better than React Navigation?
For new Expo apps, yes in most cases: routes come from files, deep links and web URLs are automatic, and native tabs are built in. React Navigation remains a strong choice for bare and brownfield apps or very custom navigation, and it's actively maintained.
Does Expo Router still use React Navigation?
Not since Expo SDK 56. Expo Router forked the parts of React Navigation it builds on, so it no longer depends on React Navigation packages. Code that imports directly from @react-navigation/* may need updating, using Expo's codemod and migration guide.
Can I use Expo Router without Expo?
Expo Router is part of the Expo ecosystem and expects an Expo project setup, but that includes bare projects using Expo modules. If you don't use Expo at all, React Navigation is the natural choice.
How do deep links work with Expo Router?
Every file in the app directory is a route with a path, so a link like yourapp://class/123 or a universal link to https://yourdomain.com/class/123 opens the matching screen automatically. You still configure the URL scheme and, for universal links, your domain association files.
Next steps
If you're choosing navigation for a new app, or weighing a move to Expo Router, I can help you decide and carry out the migration safely. Get in touch, or see how I work as a React Native developer.
Sources
- Expo Router introduction, Expo
- Native tabs, Expo
- Expo SDK 56, Expo
- React Navigation, React Navigation
Related
A React Native Project Structure That Scales Past Version 1
A React Native folder structure that scales: thin Expo Router routes, feature folders, shared primitives, one API layer, config and when to use a monorepo.
How We Cut React Native Startup Time from 3.8s to 1.5s
The levers that cut React Native startup time by about 60%: measuring cold start properly, Hermes, image optimisation and cache-first fetching.
Migrating to the New Architecture: A Field Guide from 8 Migrations
A step-by-step guide to migrating a React Native app to the New Architecture in 2026: auditing libraries, the 0.81 path, common breakages and testing.
