Blog/Quick Tips & Snippets/React Native Expo Router: Quick Setup Guide
POST
December 18, 2025
LAST UPDATEDDecember 18, 2025

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 NativeExpoRouterMobile
React Native Expo Router: Quick Setup Guide
2 min read

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:

tsx
// 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:

tsx
// 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:

tsx
// 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:

tsx
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:

json
{
  "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.

SH

Article Author

Sadam Hussain

Senior Full Stack Developer

Senior Full Stack Developer with over 7 years of experience building React, Next.js, Node.js, TypeScript, and AI-powered web platforms.

Related Articles

TypeScript Utility Types You Should Know
Feb 10, 20263 min read
TypeScript
Cheatsheet

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
Feb 08, 20262 min read
Next.js
OG Images
SEO

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
Jan 22, 20263 min read
GitHub Actions
CI/CD
DevOps

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.