Navigation with Expo Router
Modern Expo apps use Expo Router, a file-based routing system: the folder structure inside app/ directly determines your app's screens and URLs, the same idea as Next.js, applied to mobile.
Basic routes
app/
index.tsx # the "/" screen (home)
profile.tsx # the "/profile" screen
settings.tsx # the "/settings" screen
// app/profile.tsx
import { View, Text } from 'react-native';
export default function ProfileScreen() {
return (
<View>
<Text>Your profile</Text>
</View>
);
}
Each file just needs a default-exported component, Expo Router wires up the screen and navigation automatically, no manual route configuration.
Navigating between screens
import { Link, useRouter } from 'expo-router';
export default function HomeScreen() {
const router = useRouter();
return (
<View>
<Link href="/profile">Go to profile</Link>
<Button title="Go to settings" onPress={() => router.push('/settings')} />
</View>
);
}
<Link> works like an anchor tag, declarative navigation right in your JSX. useRouter() gives you an imperative API (router.push, router.back, router.replace) for navigating in response to code, like after a form submits successfully.
Dynamic routes
app/
courses/
[id].tsx # matches /courses/123, /courses/anything
// app/courses/[id].tsx
import { useLocalSearchParams } from 'expo-router';
export default function CourseScreen() {
const { id } = useLocalSearchParams();
return <Text>Course {id}</Text>;
}
Square brackets in a filename, [id].tsx, create a dynamic segment, useLocalSearchParams() reads whatever value matched that segment out of the current URL.
Layouts
A special _layout.tsx file wraps every screen in the same folder, this is where you'd add a shared tab bar, header, or navigation container:
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return <Stack />;
}