Screen
A screen represents routes in a navigator. A screen's configuration contains the component for the route, options, event listeners, etc.
- Static
- Dynamic
Screens can be defined under the screens
key in the navigator configuration:
const MyStack = createNativeStackNavigator({
screens: {
Home: HomeScreen,
Profile: ProfileScreen,
},
});
A Screen
component is returned from a createXNavigator
function. After creating the navigator, it can be used as children of the Navigator
component:
const Stack = createNativeStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
);
}
You need to provide at least a name and a component to render for each screen.
Configuration
Name
The name to use for the screen.
- Static
- Dynamic
The key in the screens
object is used as the name:
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
},
},
});
It can be passed in the name
prop to the Screen
component:
<Stack.Screen
name="Profile"
component={ProfileScreen}
/>
This name is used to navigate to the screen:
navigation.navigate('Profile');
It is also used for the name
property in the route
.
While it is supported, we recommend avoiding spaces or special characters in screen names and keeping them simple.
Options
Options are used to configure how the screen gets presented in the navigator. It accepts either an object or a function returning an object:
- Static
- Dynamic
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
options: {
title: 'Awesome app',
},
},
},
});
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={{
title: 'Awesome app',
}}
/>
When you pass a function, it'll receive the route
, navigation
and theme
as arguments:
- Static
- Dynamic
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
options: ({ route, navigation, theme }) => ({
title: route.params.userId,
}),
},
},
});
<Stack.Screen
name="Profile"
component={ProfileScreen}
options={({ route, navigation }) => ({
title: route.params.userId,
})}
/>
See Options for screens for more details and examples.
Initial params
Initial params are used as the default params for the screen. If a screen is used as initialRouteName
, it'll contain the params from initialParams
. If you navigate to a new screen, the params passed are shallow merged with the initial params.
- Static
- Dynamic
const Stack = createNativeStackNavigator({
screens: {
Details: {
screen: DetailsScreen,
initialParams: { itemId: 42 },
},
},
});
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
ID
A screen can have an ID to identify it uniquely. This is useful when you want to ensure that the screen with the same ID doesn't appear multiple times in the stack.
This can be done by specifying the getId
callback. It receives an object with the route params:
- Static
- Dynamic
const Stack = createStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
getId: ({ params }) => params.userId,
},
},
});
<Stack.Screen
name="Profile"
component={ProfileScreen}
getId={({ params }) => params.userId}
/>
In the above example, params.userId
is used as an ID for the Profile
screen with getId
. This changes how the navigation works to ensure that the screen with the same ID appears only once in the stack.
Let's say you have a stack with the history Home > Profile (userId: bob) > Settings
, consider following scenarios:
- You call
navigate(Profile, { userId: 'bob' })
: The resulting screens will beHome > Settings > Profile (userId: bob)
since the existingProfile
screen matches the ID. - You call
navigate(Profile, { userId: 'alice' })
: The resulting screens will beHome > Profile (userId: bob) > Settings > Profile (userId: alice)
since it'll add a newProfile
screen as no matching screen was found.
If getId
is specified in a tab or drawer navigator, the screen will remount if the ID changes.
If you're using @react-navigation/native-stack
, it doesn't work correctly with the getId
callback. So it's recommended to avoid using it in that case.
Component
Each screen must specify a component to render for that route.
- Static
- Dynamic
It can be passed under the screen
property in the screen configuration:
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
},
},
});
component
It can be passed in the component
prop to the Screen
component:
<Stack.Screen
name="Profile"
component={ProfileScreen}
/>
getComponent
It's also possible to pass a function in the getComponent
prop to lazily evaluate the component:
<Stack.Screen
name="Profile"
getComponent={() => require('./ProfileScreen').default}
/>
You can use this approach instead of the component
prop if you want the ProfileScreen
module to be lazily evaluated when needed. This is especially useful when using ram bundles to improve initial load.
children
Another way is to pass a render callback to return React Element to use for the screen:
<Stack.Screen name="Profile">
{(props) => <ProfileScreen {...props} />}
</Stack.Screen>
You can use this approach instead of the component
prop if you need to pass additional props. Though we recommend using React context for passing data instead.
By default, React Navigation applies optimizations to screen components to prevent unnecessary renders. Using a render callback removes those optimizations. So if you use a render callback, you'll need to ensure that you use React.memo
or React.PureComponent
for your screen components to avoid performance issues.
Layout
A layout is a wrapper around the screen. It makes it easier to provide things such as an error boundary and suspense fallback for a screen, or wrap the screen with additional UI.
It takes a function that returns a React element:
- Static
- Dynamic
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
layout: ({ children }) => (
<ErrorBoundary>
<React.Suspense
fallback={
<View style={styles.fallback}>
<Text style={styles.text}>Loading…</Text>
</View>
}
>
{children}
</React.Suspense>
</ErrorBoundary>
),
},
},
});
<Stack.Screen
name="MyScreen"
component={MyScreenComponent}
layout={({ children }) => (
<ErrorBoundary>
<React.Suspense
fallback={
<View style={styles.fallback}>
<Text style={styles.text}>Loading…</Text>
</View>
}
>
{children}
</React.Suspense>
</ErrorBoundary>
)}
/>
To specify a layout for all multiple screens, you can use screenLayout
in a group or navigator.
Navigation key
A navigation key is an optional key for this screen. This doesn't need to be unique. If the key changes, existing screens with this name will be removed (if used in a stack navigator) or reset (if used in a tab or drawer navigator).
This can be useful when we have some screens that we want to be removed or reset when the condition changes:
- Static
- Dynamic
const Stack = createNativeStackNavigator({
screens: {
Profile: {
screen: ProfileScreen,
navigationKey: 'user',
},
},
});
For the static API, we recommend using the groups
instead of the navigationKey
for each screen as you can dynamically add or remove groups with the if
property.
<Stack.Screen
navigationKey={isSignedIn ? 'user' : 'guest'}
name="Profile"
component={ProfileScreen}
/>
Event listeners
Event listeners can be used to subscribe to various events emitted for the screen. See listeners
prop on Screen
for more details.