1--- 2title: Stack 3description: Learn how to use the Stack Layout in Expo Router. 4--- 5 6import { FileTree } from '~/ui/components/FileTree'; 7import { BoxLink } from '~/ui/components/BoxLink'; 8import { BookOpen02Icon } from '@expo/styleguide-icons'; 9 10The `Stack` Layout in Expo Router wraps the [Native Stack Navigator](https://reactnavigation.org/docs/native-stack-navigator) from React Navigation, not to be confused with the legacy [JS Stack Navigator](https://reactnavigation.org/docs/stack-navigator). 11 12<FileTree files={['app/_layout.js', 'app/index.js', 'app/detail.js']} /> 13 14To create a `Stack` layout with two screens as shown in the file structure above: 15 16```js app/_layout.js 17import { Stack } from 'expo-router/stack'; 18 19export default function Layout() { 20 return <Stack />; 21} 22``` 23 24## Configure header bar 25 26Use the `screenOptions` prop to configure the header bar. 27 28```js app/_layout.js 29import { Stack } from 'expo-router'; 30 31export default function Layout() { 32 return ( 33 <Stack 34 screenOptions={{ 35 headerStyle: { 36 backgroundColor: '#f4511e', 37 }, 38 headerTintColor: '#fff', 39 headerTitleStyle: { 40 fontWeight: 'bold', 41 }, 42 }} 43 /> 44 ); 45} 46``` 47 48You can use a layout's Screen component to configure the header bar dynamically from within the route. This is good for interactions that change the UI. 49 50```js app/home.js 51import { Link, Stack } from 'expo-router'; 52import { Image, Text, View } from 'react-native'; 53 54function LogoTitle() { 55 return ( 56 <Image 57 style={{ width: 50, height: 50 }} 58 source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} 59 /> 60 ); 61} 62 63export default function Home() { 64 return ( 65 <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> 66 <Stack.Screen 67 options={{ 68 // https://reactnavigation.org/docs/headers#setting-the-header-title 69 title: 'My home', 70 // https://reactnavigation.org/docs/headers#adjusting-header-styles 71 headerStyle: { backgroundColor: '#f4511e' }, 72 headerTintColor: '#fff', 73 headerTitleStyle: { 74 fontWeight: 'bold', 75 }, 76 // https://reactnavigation.org/docs/headers#replacing-the-title-with-a-custom-component 77 headerTitle: props => <LogoTitle {...props} />, 78 }} 79 /> 80 <Text>Home Screen</Text> 81 <Link href={{ pathname: 'details', params: { name: 'Bacon' } }}>Go to Details</Link> 82 </View> 83 ); 84} 85``` 86 87You can use the imperative API `router.setParams()` function to configure the route dynamically. 88 89```js app/details.js 90import { View, Text } from 'react-native'; 91import { Stack, useLocalSearchParams, useRouter } from 'expo-router'; 92 93export default function Details() { 94 const router = useRouter(); 95 const params = useLocalSearchParams(); 96 97 return ( 98 <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> 99 <Stack.Screen 100 options={{ 101 title: params.name, 102 }} 103 /> 104 <Text 105 onPress={() => { 106 router.setParams({ name: 'Updated' }); 107 }}> 108 Update the title 109 </Text> 110 </View> 111 ); 112} 113``` 114 115## Header buttons 116 117With the following file structure: 118 119<FileTree files={['app/_layout.js', 'app/home.js']} /> 120 121You can use the `<Stack.Screen name={routeName} />` component in the layout component route to statically configure screen options. This is useful for tab bars or drawers which need to have an icon defined ahead of time. 122 123```js app/_layout.js 124import { Stack } from 'expo-router'; 125 126export default function Layout() { 127 return ( 128 <Stack 129 // https://reactnavigation.org/docs/headers#sharing-common-options-across-screens 130 /* @info */ 131 screenOptions={{ 132 headerStyle: { 133 backgroundColor: '#f4511e', 134 }, 135 headerTintColor: '#fff', 136 headerTitleStyle: { 137 fontWeight: 'bold', 138 }, 139 }}> 140 /* @end */ 141 {/* Optionally configure static options outside the route. */} 142 /* @info */ 143 <Stack.Screen name="home" options={{}} /> 144 /* @end */ 145 </Stack> 146 ); 147} 148``` 149 150Use the `<Stack.Screen />` component in the child route to dynamically configure options. 151 152```js app/home.js 153import { useLayoutEffect } from 'react'; 154import { View, Button, Text, Image } from 'react-native'; 155/* @info */ 156import { Stack } from 'expo-router'; 157/* @end */ 158 159function LogoTitle() { 160 return ( 161 <Image 162 style={{ width: 50, height: 50 }} 163 source={require('@expo/snack-static/react-native-logo.png')} 164 /> 165 ); 166} 167 168export default function Home() { 169 const [count, setCount] = React.useState(0); 170 171 return ( 172 <> 173 /* @info */ 174 <Stack.Screen 175 options={{ 176 headerTitle: props => <LogoTitle {...props} />, 177 headerRight: () => <Button onPress={() => setCount(c => c + 1)} title="Update count" />, 178 }} 179 /> 180 /* @end */ 181 <Text>Count: {count}</Text> 182 </> 183 ); 184} 185``` 186 187## Next steps 188 189<BoxLink 190 title="Native Stack Navigator: Options" 191 Icon={BookOpen02Icon} 192 description="For a list of all options, see React Navigation's documentation." 193 href="https://reactnavigation.org/docs/native-stack-navigator#options" 194/> 195 196<BoxLink 197 title="Tabs layout" 198 Icon={BookOpen02Icon} 199 description="Learn how to use Tabs layout in Expo Router." 200 href="/router/advanced/tabs" 201/> 202