Introduction
Expo Router brings file-based routing to React Native, similar to Next.js. Create routes by adding files to your app directory. This guide covers everything you need.
How It Works
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Expo Router Concept โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ File System = Routes โ
โ โ
โ app/ Screen โ
โ โโโ _layout.tsx โ Root layout โ
โ โโโ index.tsx โ / (Home) โ
โ โโโ about.tsx โ /about โ
โ โโโ users/ โ /users โ
โ โ โโโ _layout.tsx โ Users layout โ
โ โ โโโ index.tsx โ /users โ
โ โ โโโ [id].tsx โ /users/:id โ
โ โโโ (stack).tsx โ Optional segment โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Basic Setup
Installation
npx create-expo-app@latest my-app
cd my-app
npx expo-router start
Configuration
// app.json
{
"expo": {
"scheme": "myapp",
"web": {
"bundler": "metro"
}
}
}
Creating Routes
Simple Routes
// app/index.tsx - Home screen
import { View, Text } from 'react-native';
import { Link } from 'expo-router';
export default function Home() {
return (
<View>
<Text>Welcome!</Text>
<Link href="/about">Go to About</Link>
</View>
);
}
// app/about.tsx - About screen
import { View, Text } from 'react-native';
import { Stack } from 'expo-router';
export default function About() {
return (
<View>
<Stack.Screen options={{ title: 'About Us' }} />
<Text>About page content</Text>
</View>
);
}
Layouts
// app/_layout.tsx - Root layout
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack>
<Stack.Screen name="index" options={{ title: 'Home' }} />
<Stack.Screen name="about" options={{ title: 'About' }} />
</Stack>
);
}
// app/tabs/_layout.tsx - Tab layout
import { Tabs } from 'expo-router';
export default function TabLayout() {
return (
<Tabs>
<Tabs.Screen name="index" options={{ title: 'Home' }} />
<Tabs.Screen name="profile" options={{ title: 'Profile' }} />
</Tabs>
);
}
Dynamic Routes
Parameters
// app/users/[id].tsx - Dynamic route
import { useLocalSearchParams } from 'expo-router';
export default function UserProfile() {
const { id } = useLocalSearchParams();
return (
<View>
<Text>User ID: {id}</Text>
</View>
);
}
// app/posts/[...slug].tsx - Catch-all route
import { useLocalSearchParams } from 'expo-router';
export default function Post() {
const { slug } = useLocalSearchParams();
const slugArray = Array.isArray(slug) ? slug : [slug];
return (
<Text>Post: {slugArray.join('/')}</Text>
);
}
Multiple Parameters
// app/users/[id]/posts/[postId].tsx
import { useLocalSearchParams } from 'expo-router';
export default function UserPost() {
const { id, postId } = useLocalSearchParams();
return (
<Text>
User {id}'s post: {postId}
</Text>
);
}
Navigation
Programmatic Navigation
import { useRouter } from 'expo-router';
export function LoginButton() {
const router = useRouter();
return (
<Button onPress={() => router.push('/dashboard')}>
Login
</Button>
);
}
// Navigate with params
router.push({
pathname: '/users/[id]',
params: { id: '123' }
});
// Go back
router.back();
// Replace (no back navigation)
router.replace('/home');
Deep Linking
// app.json
{
"expo": {
"scheme": "myapp",
"extra": {
"eas": {
"projectId": "..."
}
}
}
}
// Deep link to screen
// myapp://users/123
API Reference
# Available hooks
hooks:
- "useRouter" - Navigate programmatically
- "useLocalSearchParams" - Get route params
- "useGlobalSearchParams" - Global URL params
- "useNavigation" - React Navigation API
- "useSegments" - Current route segments
Key Takeaways
- File-based routing - Routes from file structure
- Layouts - Shared UI for groups
- Dynamic routes - Parameters in URLs
- Deep linking - Built-in support
Comments