What is Expo Router? How does it implement file system routing?
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.