Screen stack and header
A stack is the main kind of navigation on a phone. A new screen is placed on top of the previous one, and the back button removes it and returns to the previous screen. The stack and the header with a title are configured in the layout file app/_layout.tsx.
A layout with a stack
After npm run reset-project the layout already contains a stack:
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return <Stack />;
}Stack shows the current screen with a header above it. Screens from the app folder join the stack automatically, and the header title is the file name: index, about.
Titles and header style
Titles and the overall look are set in the layout:
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack
screenOptions={{
headerStyle: { backgroundColor: '#2563eb' },
headerTintColor: '#fff',
}}
>
<Stack.Screen name="index" options={{ title: 'Blog' }} />
<Stack.Screen name="about" options={{ title: 'About' }} />
</Stack>
);
}The header turns blue with white text, and the titles become "Blog" and "About". screenOptions applies to all screens, options on a Stack.Screen to one; name is the file path without the extension.
| Option | What it does |
|---|---|
title | Title text |
headerShown | false hides the header |
headerStyle | Header background |
headerTintColor | Color of the title and the back arrow |
presentation | 'modal' opens the screen from the bottom, like a modal |
A title from the screen itself
If the title depends on the screen's data, set it inside the screen by rendering Stack.Screen in the markup:
// app/about.tsx
import { Stack } from 'expo-router';
import { Text, View } from 'react-native';
export default function About() {
return (
<View style={{ flex: 1, padding: 16 }}>
<Stack.Screen options={{ title: 'About the authors' }} />
<Text>This app was written by Anna and Oleg.</Text>
</View>
);
}Nothing extra appears on the screen, and the header says "About the authors".
Navigating from code
Sometimes you need to navigate not via a link but after an action, for example after saving a form. The useRouter hook does this:
// app/index.tsx
import { useRouter } from 'expo-router';
import { Button, View } from 'react-native';
export default function Index() {
const router = useRouter();
return (
<View style={{ flex: 1, padding: 16 }}>
<Button title="About" onPress={() => router.push('/about')} />
</View>
);
}Pressing the button opens the "About" screen on top of the main one.
| Method | What it does |
|---|---|
router.push('/about') | Places a screen on top of the current one |
router.back() | Returns to the previous screen |
router.replace('/about') | Replaces the current screen, with no way back |
Common mistake
Giving Stack.Screen a name that does not match any file: name="About" for the file about.tsx. Names are case-sensitive, so the options are not applied and the terminal shows a warning. name must match the file path inside app without the extension: about, posts/[id].