Options come from three places: a navigator's screenOptions (all its screens), a layout's Stack.Screen options (one screen), and the screen itself while it renders, the only place that knows the data. BookNest's book screen titles itself with the book's name and adds a share button that reuses shareBook() from Sharing a Book from BookNest:
<ScrollView contentContainerStyle={{ padding: 16, gap: 12 }}>
<Stack.Screen options={{
title: book.title,
headerRight: () => <Ionicons name="share-social-outline" size={24} color="#1565c0"
accessibilityLabel="Share" onPress={() => shareBook(book)} />,
}} />A <Stack.Screen> rendered inside a screen draws nothing; it passes its options up to the navigator, and it is the Expo Router 6,418 spelling of React Navigation 407,918 's navigation.setOptions(). The layout sets title: '' for this route: the default title is the route name, so the header would otherwise show book/[id] until the screen renders. The right side of the figure in Stacks, Tabs, Drawers shows the result. The options you will use most:
| Option | Effect |
|---|---|
| title, headerTitle | Text, or a component, in the header |
| headerShown | false hides the header, for a screen that draws its own |
| headerLeft, headerRight | Buttons beside the title |
| headerStyle, headerTintColor | Background; color of title, arrow and buttons |
| presentation | card, modal, transparentModal, formSheet |
| tabBarBadge, tabBarIcon, drawerLabel | Tab and drawer entries |
Native-stack headers are platform views (an Android toolbar, an iOS UINavigationBar), so a custom header: () => ... gives up some native behavior. Give icon-only header buttons an accessibilityLabel, as the share button has, and a touch target of about 48 dp, Android's recommended minimum (Accessibility and i18n).