Expo Router is the official routing solution provided by Expo, based on file system routing and designed specifically for Expo apps. It simplifies navigation management, providing type-safe routing and deep linking support.
Core Features:
-
File System Routing
- Automatically generates routes based on file and folder structure
- Supports dynamic routes and nested routes
- Similar routing experience to Next.js
-
Type Safety
- Automatically generates TypeScript types
- Compile-time route checking
- Intelligent code completion
-
Deep Linking
- Native deep linking support
- Web URL compatibility
- Automatic link parameter handling
Installation and Configuration:
bash# Install Expo Router npx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar # Configure app.json { "expo": { "scheme": "myapp", "experiments": { "typedRoutes": true } } }
Project Structure:
shellapp/ ├── _layout.tsx # Root layout ├── index.tsx # Home page (/) ├── about.tsx # About page (/about) ├── user/ │ ├── [id].tsx # User detail page (/user/:id) │ └── settings.tsx # User settings (/user/settings) ├── (tabs)/ │ ├── _layout.tsx # Tab layout │ ├── home.tsx # Tab home │ └── profile.tsx # Tab profile └── (modal)/ └── _layout.tsx # Modal layout
Route Types:
- Static Routes
typescript// app/index.tsx export default function HomeScreen() { return <Text>Home</Text>; }
- Dynamic Routes
typescript// app/user/[id].tsx import { useLocalSearchParams } from 'expo-router'; export default function UserScreen() { const { id } = useLocalSearchParams<{ id: string }>(); return <Text>User: {id}</Text>; }
- Nested Routes
typescript// app/(tabs)/_layout.tsx import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs> <Tabs.Screen name="home" options={{ title: 'Home' }} /> <Tabs.Screen name="profile" options={{ title: 'Profile' }} /> </Tabs> ); }
- Group Routes
typescript// (tabs) and (modal) are route groups, don't affect URL // app/(tabs)/home.tsx -> /home // app/(modal)/settings.tsx -> /settings
Navigation API:
typescriptimport { useRouter, useSegments } from 'expo-router'; function MyComponent() { const router = useRouter(); const segments = useSegments(); // Navigate to page const navigateToUser = () => { router.push('/user/123'); }; // Replace current page const replacePage = () => { router.replace('/settings'); }; // Go back const goBack = () => { router.back(); }; // Check current route const isHome = segments[0] === 'home'; return ( <View> <Button title="Go to User" onPress={navigateToUser} /> <Button title="Replace" onPress={replacePage} /> <Button title="Back" onPress={goBack} /> </View> ); }
Linking API:
typescriptimport { Link, useLocalSearchParams } from 'expo-router'; // Use Link component <Link href="/user/123"> <Text>Go to User</Text> </Link> // Get parameters with useLocalSearchParams const { id } = useLocalSearchParams<{ id: string }>();
Deep Linking Configuration:
typescript// app/_layout.tsx import { Stack } from 'expo-router'; import * as Linking from 'expo-linking'; const linking = { prefixes: [Linking.createURL('/')], config: { screens: { index: '/', user: '/user/:id', }, }, }; export default function RootLayout() { return <Stack />; }
Best Practices:
-
Route Organization: Use route groups and nested layouts reasonably to keep structure clear
-
Type Safety: Enable typedRoutes experimental feature for complete type support
-
Performance Optimization: Use lazy loading to reduce initial bundle size
-
Error Handling: Implement 404 pages and error boundaries
-
Test Coverage: Write unit tests for routing logic
Comparison with React Navigation:
Expo Router is built on top of React Navigation, providing a higher level of abstraction:
- Simpler configuration
- Automatic type generation
- File system routing
- Better deep linking support
Expo Router is the ideal choice for building navigation in Expo apps, especially for projects that need type safety and deep linking.