Nesting Tab and Stack Navigators in React Native and Expo Apps

Aman Mittal
Heartbeat
Published in
7 min readFeb 26, 2020

--

Navigation is an essential part of any mobile app that has multiple screens leading to a variety of interactions for the user. Building a working navigation system often requires us to create a structure that allows for different kinds of navigators working together.

Using react-navigation, you can definitely nest different types of navigators in a React Native app. The term nesting, when it comes to navigators, refers to rendering one navigator inside a screen of another navigator.

The need to nest navigators arises when you want a user to respond to different sections of the app. For example, an app that requires a user to enter credentials to access different features of the app—they have to go through either a login or signup screen. The home or the main screen might contain different tabs (think of Instagram), but the login and sign up screens are two separate screens that are pushed and pop one after the other.

A few of the possible scenarios for using nesting navigators include:

  • Stack navigator nested inside drawer navigator
  • Tab navigator nested inside stack navigator
  • Stack navigator nested inside a tab navigator

In this tutorial, let’s examine one of the above scenarios by nesting a tab navigator inside a stack navigator. Whether you’re following from the previous tutorial on building a stack navigator using a component-based configuration with the latest version of the react-navigation library (link below), or not, here’s the source code of the Expo demo app that’s going to be leveraged. This demo app already has a stack navigator running—you can download the source code from the GitHub repo here.

You can read the complete post on setting up a Stack Navigator using react-navigation version 5 here:

Table of contents

  • Install dependencies
  • Create a mock screen
  • Create a tab navigator
  • Adding icon and changing active tint color
  • Passing screenOptions in a tab navigator
  • Updating the header title for the nested child navigator
  • Conclusion

Requirements

Requirements for this tutorial are simple. Have the following installed on your local dev environment:

  • Node.js version >= 10.x.x installed
  • Have access to one package manager such as npm or yarn
  • Latest expo-cli version installed or use npx

Do note that, without digging much into the configuration of native binaries with the react-navigation library, I’m going to use a project that’s already generated using expo-cli. If you wish to start fresh, choose the blank template.

Install dependencies

Install the following dependency to set up a tab navigator. Run the following command from a terminal window:

This package will allow the app to have a simple tab bar appear at the bottom of the screen and switch between different routes. The demo app we’re going to build will consist of two tabs. We’re going to nest the tab navigator inside the stack navigator and create a mock screen for the second tab.

Create a mock screen

Even though the current app structure has three different screen components (open src/screens to view them), let’s create another screen component called Profile that will act as the second tab. Create a new file called src/screens/Profile.js with the following code snippet:

Create a tab navigator

In this section, let’s set up a basic tab navigator. Start by renaming the file MainStackNavigator to AppNavigator.js in the directory src/navigation.

After renaming the routes config file, and after other import statements, import the createBottomTabNavigator from @react-navigation/bottom-tabs, as well as the Profile screen component.

Then create an instance of the createBottomTabNavigator called Tab as shown below:

Next, create a function called MainTabNavigator(). Using Tab.Navigator, you can define the structure of the routes, and using Tab.Screen, you can define each of the routes.

Let’s define the following tab routes for now: Home and Profile.

Now, in the MainStackNavigator(), instead of passing the Home screen, let’s pass the MainTabNavigator.

Lastly, to make all of this work, open the App.js file in the root of the project and modify the statement that imports the MainStackNavigator with the correct file name:

Go back to the terminal window, execute expo start, and open up an Expo client inside a simulator or a real device. You’re going to get the following result:

Adding an icon and changing active tint color

From the last image, you’ll notice that the active tab is highlighted by a blue tint color, and the non-active tab is gray. Let’s change this tint color.

Open the AppNavigator.js file, and in the Tab.Navigator add a prop called tabBarOptions. This prop allows you to customize the tab bar shared between different routes.

Add the following:

Go to the simulator device—you’re going to notice that the active tab bar label is black, a change from the previous blue.

Let’s add some icons to the tab bar. Start by importing the Ionicons from @expo/vector-icons.

Then, in each Tab.Screen, add an options prop that has a property of tabBarIcon. This function returns the component Ionicons. Pass the arguments color and size to maintain the active tint color.

Here is the output:

You can even change the background of the tab bar by adding a style property to tabBarOptions.

Here’s the output for the above snippet:

Passing screenOptions in a Tab Navigator

The previous section is one way to add icons to each route or screen in the tab bar. There’s another way you can do it by passing screenOptions in the wrapper Tab.Navigator. This prop is used to modify or add common styles to a navigator.

There’s no change in the actual function of the tab navigator from the previous section, as you can notice below:

Updating the header title for the nested child navigator

Right now, the title for each tab screen is going to be the same. This is because the root navigator (which here is the stack navigator) structure is going to look at its immediate children, which are the Home, Detail, and Settings screens. In the current scenario, if you’re to set the title for the Profile screen passing the prop options, it isn’t going to work.

This is because the Profile screen is a child of the tab navigator and not the stack navigator. The tab navigator is nested inside the stack navigator, and thus, profile isn’t the immediate child to the stack navigator.

For each tab to have its own title (since the tab navigator is nested inside the stack navigator), you have to determine the title for a specific tab screen based on the navigation state from the property route.state.

This can be done by defining a helper function called getHeaderTitle that has route as its parameter. Why pass route? Because it contains the state property, which refers to the child's navigator state, and the value of the currently active route name can be obtained from this state.

Add a function called getHeaderTitle in the AppNavigator.js file:

Then, as per the recommended method, add the options prop to the Stack.Screen route, whose value is Home.

Now, when visiting the Profile tab, you’re going to get the desired title in the header.

Conclusion

Congratulations! You’ve completed this tutorial.

In this tutorial, we discuss only one scenario for nesting navigators. The main objective here was to become familiar with the component-based configuration of the tab navigator in the latest version of the react-navigation library.

The link to the complete Tab Navigator API is here, and I’d recommend you to check it out.

You can find the complete code for this tutorial at this GitHub repo.

If you’d like to receive more React Native tutorials in your inbox, you can sign up for my newsletter here.

Editor’s Note: Heartbeat is a contributor-driven online publication and community dedicated to providing premier educational resources for data science, machine learning, and deep learning practitioners. We’re committed to supporting and inspiring developers and engineers from all walks of life.

Editorially independent, Heartbeat is sponsored and published by Comet, an MLOps platform that enables data scientists & ML teams to track, compare, explain, & optimize their experiments. We pay our contributors, and we don’t sell ads.

If you’d like to contribute, head on over to our call for contributors. You can also sign up to receive our weekly newsletters (Deep Learning Weekly and the Comet Newsletter), join us on Slack, and follow Comet on Twitter and LinkedIn for resources, events, and much more that will help you build better ML models, faster.

--

--

👨‍💻Developer 👉 Nodejs, Reactjs, ReactNative | Tech Blogger with 3M+ views at Medium| My blog 👉 https://amanhimself.dev