Skip to main content
Version: 8.x

Nesting navigators

Nesting navigators means rendering a navigator inside a screen of another navigator, for example:

const HomeTabs = createBottomTabNavigator({
screens: {
Feed: createBottomTabScreen({
screen: FeedScreen,
}),
Messages: createBottomTabScreen({
screen: MessagesScreen,
}),
},
});

const RootStack = createNativeStackNavigator({
screens: {
Home: createNativeStackScreen({
screen: HomeTabs,
options: {
headerShown: false,
},
}),
Profile: createNativeStackScreen({
screen: ProfileScreen,
}),
},
});

In this example, a tab navigator (HomeTabs) is nested inside a stack navigator (RootStack) under the Home screen. The structure looks like this:

  • RootStack (Stack navigator)
    • HomeTabs (Tab navigator)
      • Feed (screen)
      • Messages (screen)
    • Profile (screen)

Nesting navigators works much like nesting regular components. To achieve the behavior you want, it's often necessary to nest multiple navigators.

How nesting navigators affects the behaviour

When nesting navigators, there are some things to keep in mind:

Each navigator keeps its own navigation history

Let's say you have a stack navigator (let's call it StackA) nested within another navigator (let's call it NavigatorB). When you press the back button in a screen inside StackA, it will go to the previous screen of the closest ancestor navigator of the screen - i.e. StackA.

If the current screen is the first screen in StackA, then pressing back will go to the previous screen in NavigatorB.

Each navigator has its own options

Specifying a title option in a screen nested in a child navigator won't affect the title shown in a parent navigator.

If you want to achieve this behavior, see the guide for screen options with nested navigators. this could be useful if you are rendering a tab navigator inside a stack navigator and want to show the title of the active screen inside the tab navigator in the header of the stack navigator.

Each screen in a navigator has its own params

Any params passed to a screen in a nested navigator are in the route object of that screen and aren't accessible from a screen in a parent or child navigator.

If you need to access params of the parent screen from a child screen, you can pass the name of the screen to the useRoute hook to get the route object of the parent screen:

const route = useRoute('ParentScreenName');

console.log(route.params);

Actions like navigate and goBack are handled by the current navigator first. If it can't handle the action, the parent navigator tries. For example, calling navigate('Messages') from Feed is handled by the tab navigator, but navigate('Settings') bubbles up to the parent stack.

If you have a stack inside a drawer navigator, the drawer's openDrawer, closeDrawer, toggleDrawer methods etc. will also be available on the navigation object in the screens inside the stack navigator. But say you have a stack navigator as the parent of the drawer, then the screens inside the stack navigator won't have access to these methods, because they aren't nested inside the drawer.

Similarly, if you have a tab navigator inside stack navigator, the screens in the tab navigator will get the push and replace methods for stack in their navigation object.

Nested navigators don't receive parent's events

Screens in a nested navigator won't receive the events emitted by the parent tab navigator such as tabPress when using navigation.addListener. We can get the parent navigation object with navigation.getParent to listen to parent events: