How to build a nested drawer menu with React Native

Dhruvdutt Jadhav
We’ve moved to freeCodeCamp.org/news
6 min readApr 25, 2018

--

Screen space is a precious commodity on mobile. The drawer menu (or “hamburger menu”) is one of the most popular navigation patterns that helps you save it while offering intuitive navigation. In this post, I will demystify how to build a nested (multi-level) drawer menu using React Native and React Navigation. 🔰

Nested Drawers in React Native

Try the live demo on mobile📱or on web. 🕸️

Navigation in React Native ⚛️

Navigation forms the backbone of a huge majority of apps built for production. The look and feel of navigation are important for driving use and engagement in mobile apps.

However, if you are React Native developer, there isn’t a clear opinion when it comes to building a navigation menu. React Native recommends a bunch of libraries for navigation. Each has its strength, depending on your needs, but there’s no one clear winner for all use-cases.

None of the navigation libraries currently support nested drawers out-of-the-box. But one of the libraries that provides a rich API to build custom solutions is React Navigation — a JavaScript-based navigation. It is strongly backed and maintained by the React Native community. This is what we’re going to use in this tutorial.

The use case 🕵️

I had to build a playground app to showcase a UI components library for React Native. It consists of eight different components, each supporting various props, and more than 50 different options.

It was not possible to show all options inside the drawer at one time without a multi-level drawer which would scope the options based on the selected component. I couldn’t find a ready-made solution for this, so I needed to build a custom one.

Base setup 👷

For the base setup, I’m assuming you already have a React Native project setup with either CRNA, Expo Kit, or React Native CLI. Make sure you have the react-navigation library installed with either yarn or npm. We’ll start right off with using the navigation API.

Feel free to check the getting-started guide before proceeding if you aren’t familiar with the React Navigation API.

We’ll start with an example similar to the one documented in the React Navigation’s DrawerNavigator official guide. We’ll create a simple drawer that has two drawer items: Home and Notifications.

Create DrawerNavigator with two items.
Base Setup

Custom drawer content

React Navigation enables all navigators to do a lot of customizations by passing a navigator config as the second parameter. We’ll use it to render some custom content other than the stock drawer items.

DrawerNavigator(RouteConfigs, DrawerNavigatorConfig)

We’ll pass a prop called contentComponent to the config which would allow us to render custom content for the drawer. We’ll use that to show a header and footer along with the prevailing DrawerItems from react-navigation.

Code for navigation config with content component.
DrawerNavigator: Content Component

This potentially unlocks a lot of things that can be done by controlling what to render inside the drawer.

Creating screen mapping

We need to build a nested drawer for each component that we want to showcase. So let’s first register all the screens with the DrawerNavigator’s Config. We’ve created a separate screen mapping file for components. You can very well have your own convention, or define the object directly similar to the Home screen component.

Register all screen components. Here’s the full code.

The screen mapping consists of simple objects with screen property. The screenMapping object looks something like this:

After registering all components, the drawer would look something like this:

Registering all components along with child options

This would render all the components along with their options. We have two main components: DataSearch and TextField. Each has options like “With Icon Position,” “With Placeholder,” and more. Our task is to segregate these into a list of only components (DataSearch, TextField).

Grouping outer drawer

A pattern I followed in the mapping was to use a delimiter _ to group together options from one component. For instance, the navigation keys I used were “DataSearch_Basic” and “DataSearch_With Icon Position”. This is exactly what is going to help us combine the options for a single component like DataSearch. We’ll evaluate uniquely all the components we need to show for the outer drawer.

We’ll create a util function to evaluate outer drawer list items to render.

Util function to evaluate outer drawer list items

This function will return an object with unique components for the main components like (DataSearch, TextField) that we’ll render on the screen with the help of the contentComponent custom component. We’ll also maintain a boolean to determine the content rendered on the drawer at a particular instant.

Evaluate and render main drawer components using the util function

The renderMainDrawerComponent is just a function iterating over the keys of the components object. It renders custom outer drawer items built on top of simply Text and View from react-native. Check the full code here.

Rendering custom outer drawer items based on keys from the components objects

This will render the drawer like this:

Showing only the outer component drawer items

Rendering the child drawer 🧒

Now, we need to show the options based on the component that is tapped. You might have noticed that in utils, we’re also extracting the start and end indexes of the component groups based on the delimiter pattern.

For instance, DataSearch screens start at index 1 (index 0 is Home screen) and ends at 3. TextField starts at 3 and end at 5. We’ll use these indices to magically slice the items that are passed to DrawerItems based on the selected component and its indices.

Scoping child drawer items based on start, end index of a component

Now, after tapping on DataSearch, the drawer will yield into something like this:

Child components for a selected component

We’ve also added a sweet back button which basically toggles a boolean to render the main drawer items. You can check the full code here.

Now, the only thing left to do is make the drawer items look cleaner by trimming the redundant component name. Again, the rich React Navigation API comes handy here.

There are various properties we can pass with navigationOptions. A particular one we’re going to use here is the title prop with the screen mapping. This will let us remove the part before the first delimiter. So, “DataSearch_Basic” will show as “Basic” only.

Trimming the redundant component name part from the drawer title
Child drawer items

That’s all. We can add as many items we want based on the delimiter pattern. The playground app we’ve built consists of eight main components and over 53 total options.

Here’s the link to the final app and the codebase.

Summary 📝

  • Base setup: DrawerNavigation hello world from docs.
  • Custom drawer content: Render drawer items with contentComponent.
  • Screen mapping: Define and register all drawers components.
  • Group outer drawer: Read delimiter pattern to group drawer items.
  • Rendering child drawer: Slice and render child drawer items.

Conclusion 🎬

We learned to build a multi-level drawer menu with React Native. We used React Navigation API to render a custom content component inside the drawer, and used the delimiter pattern for screen mapping. Use this pattern to build any level of nesting or conditional rendering for drawers.

Follow me on GitHub and Twitter for more updates. 🚀

--

--