Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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.

OptionWhat it does
titleTitle text
headerShownfalse hides the header
headerStyleHeader background
headerTintColorColor 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".

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.

MethodWhat 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].

Thanks for reading!

Donate to the site — we work hard for you.