React Native Expo Router: Quick Setup Guide
Set up file-based routing in React Native with Expo Router, including tab navigation, stack navigation, deep linking, and typed route params.
Tags
React Native Expo Router: Quick Setup Guide
TL;DR
Expo Router brings Next.js-style file-based routing to React Native. Drop files in the app/ directory, and they become screens. Layouts, tab navigation, typed routes, and deep linking work out of the box.
The Problem
React Navigation requires you to manually define every screen, navigator, and route param type. For a medium-sized app, the navigation configuration file becomes a sprawling mess of nested navigators, screen options, and type definitions. Adding a new screen means touching the navigation config, the screen component, and the type definitions — three files for one new page.
The Solution
Install Expo Router and define screens by creating files in the app/ directory. The file path becomes the route.
Project structure:
app/
├── _layout.tsx # Root layout (wraps all screens)
├── index.tsx # Home screen (/)
├── settings.tsx # Settings screen (/settings)
├── (tabs)/
│ ├── _layout.tsx # Tab navigator layout
│ ├── home.tsx # Tab: Home
│ ├── search.tsx # Tab: Search
│ └── profile.tsx # Tab: Profile
└── post/
└── [id].tsx # Dynamic route (/post/123)
Root layout with Stack navigation:
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="settings" options={{ title: 'Settings' }} />
<Stack.Screen name="post/[id]" options={{ title: 'Post' }} />
</Stack>
);
}Tab navigation layout:
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Home, Search, User } from 'lucide-react-native';
export default function TabLayout() {
return (
<Tabs screenOptions={{ tabBarActiveTintColor: '#3b82f6' }}>
<Tabs.Screen
name="home"
options={{ title: 'Home', tabBarIcon: ({ color }) => <Home color={color} /> }}
/>
<Tabs.Screen
name="search"
options={{ title: 'Search', tabBarIcon: ({ color }) => <Search color={color} /> }}
/>
<Tabs.Screen
name="profile"
options={{ title: 'Profile', tabBarIcon: ({ color }) => <User color={color} /> }}
/>
</Tabs>
);
}Dynamic routes with typed params:
// app/post/[id].tsx
import { useLocalSearchParams } from 'expo-router';
import { Text, View } from 'react-native';
export default function PostScreen() {
const { id } = useLocalSearchParams<{ id: string }>();
return (
<View>
<Text>Post ID: {id}</Text>
</View>
);
}Type-safe navigation with Link and router:
import { Link, useRouter } from 'expo-router';
// Declarative navigation
<Link href="/post/42">View Post</Link>
// Imperative navigation
const router = useRouter();
router.push('/post/42');
router.replace('/settings');
router.back();Enable typed routes in app.json for compile-time route validation:
{
"expo": {
"experiments": {
"typedRoutes": true
}
}
}With typed routes enabled, router.push('/nonexistent') produces a TypeScript error, catching broken navigation links at build time.
Why This Works
File-based routing eliminates the navigation configuration boilerplate. The file system is the router — no registration, no navigator nesting, no separate type definitions. Expo Router generates deep links automatically from the file paths, so /post/42 works as both an in-app route and a URL that opens the app to that screen. The (tabs) group convention (parentheses) creates a navigator without adding a route segment, keeping URLs clean. And _layout.tsx files let you wrap groups of screens with shared UI like tab bars, headers, or auth guards.
FAQ
What is Expo Router?
Expo Router is a file-based routing library for React Native that uses the app directory convention to define screens, similar to Next.js App Router.
Does Expo Router support deep linking automatically?
Yes, every route in Expo Router gets automatic deep linking based on the file path, with no additional configuration needed for universal links.
Can I use tab and stack navigation with Expo Router?
Yes, use _layout.tsx files with Tabs or Stack components to define tab bars and stack navigators using the same file-based routing convention.
Collaboration
Need help with a project?
Let's Build It
I help startups and established companies design, build, and scale world-class digital products. From deep technical architecture to pixel-perfect UI — let's bring your vision to life.
Related Articles
TypeScript Utility Types You Should Know
Five essential built-in generic utility types in TypeScript that will save you hundreds of lines of code.
Generate Dynamic OG Images in Next.js
Generate dynamic Open Graph images in Next.js using the ImageResponse API with custom fonts, gradients, and data-driven content for social sharing.
GitHub Actions Reusable Workflows: Stop Repeating Yourself
Create reusable GitHub Actions workflows with inputs, secrets, and outputs to eliminate YAML duplication across repositories and teams efficiently.