Drawer Navigation for React Native with React Native Elements

I recently started building mobile app using React Native and started liking on how fast I can build the mobile app. There were few issues I’ve ran into while setting up which I’ll share here and show you how we can setup the drawer navigation.

My machine setup

  • Mac OS v10.14
  • Node v11.0.0
  • XCode v9.4.1
  • iPhone X Simulator v11.2
  • Android 8.1 Google Pixel 2 Emulator with SDK API 27 x86 CPU

Setup

I’m using Node v11.0.0, however this has been tested in Node v8.x.

React Native CLI v2.0.1 (Run npm i -g react-native-cli).

Setup a project by running react-native init DrawerNavigationDemo

Change the directory to cd DrawerNavigationDemo

Install the React Navigation package:

npm i -S react-navigation
npm i -S react-native-gesture-handler

Then link the packages by running react-native link

I installed react-navigation and react-native-gesture-handler packages at one shot (npm i -S react-navigation react-native-gesture-handler), even though the document shows it as a two step. And then I ran react-native link. This caused an issue, I was getting Undefined object error at Gesture Handler. I’m not pretty sure on why this happens. I’ve solved this by installing react-navigation first and then the react-native-gesture-handler next.

Directory Structure

alt text

All the folders and files are generated by react-native init command that we have run earlier, except screens and components folder.

Add Screens

Let’s add our first screen and we call it as HomeScreen. Create HomeScreen.js under screens/ directory and add the following code:

import React from 'react'
import { View, Text } from 'react-native'

const HomeScreen = () => {
  return (
    <View>
      <Text>This is Home Screen</Text>
    </View>
  )
}

export default HomeScreen

The above code just adds a text field in the mobile view, nothing much fancy here.

Create another screen called SettingsScreen.js under screens/ directory with the following code:

import React from 'react'
import { View, Text } from 'react-native'

const SettingsScreen = () => {
  return (
    <View>
      <Text>This is Settings Screen</Text>
    </View>
  )
}

export default SettingsScreen

Modify App.js

Now we have screens, let’s add drawer navigation to navigate to these screens. To do that, we have to replace the code of App.js with the following:

import { createDrawerNavigator, createAppContainer } from 'react-navigation'

import HomeScreen from './screens/HomeScreen'
import SettingsScreen from './screens/SettingsScreen'

const AppNavigator = createDrawerNavigator({
  Home: {
    screen: HomeScreen
  },
  Settings: {
    screen: SettingsScreen
  }
})

export default createAppContainer(AppNavigator)

We create the drawer navigation using the method createDrawerNavigator from react-navigation and configure with list of screens. Here we have two screens Home and Settings.

Then we export the app with createAppContainer higher-order function from react-navigation. This is required to access the navigation props in our screen components.

We’ve everything to run our app now. Let’s run it by using: react-native run-ios

You should be able to pull the drawer from the left side of the simulator.

alt text

Wow! Under 5 minutes we’ve added the drawer navigation.

Let’s style it up by adding header with Hamburger menu.

Add Header

We use React Native Elements to add few styled native elements to our app. To add, please run npm i -S react-native-elements and then run npm i -S react-native-vector-icons as this is a peer dependency by react-native-elements.

We’ll have to link the packages again, run react-native link.

Create a MyHeader.js file under components\ directory and add the following code:

import React from 'react'
import { Header } from 'react-native-elements'

import HamburgerMenu from './HamburgerMenu'

const MyHeader = props => {
  return (
    <Header
      leftComponent={<HamburgerMenu navigation={props.navigation} />}
      centerComponent={{
        text: props.title,
        style: { color: '#fff', fontWeight: 'bold' }
      }}
      statusBarProps={{ barStyle: 'light-content' }}
    />
  )
}

export default MyHeader

Here, we’re using Header component from react-native-elements package and configuring with leftComponent and centerComponent. The left component is the HamburgerMenu and the center component is the title of the screen.

Let’s create HamburgerMenu.js under components\ directory:

import React from 'react'
import { Icon } from 'react-native-elements'

const HamburgerMenu = props => {
  return (
    <Icon
      color="#fff"
      name="menu"
      onPress={() => props.navigation.toggleDrawer()}
    />
  )
}

export default HamburgerMenu

We added the icon with 3 dashes which is called as Hamburger menu and while pressing the icon, we toggle the drawer navigation.

Now we’ve our own header with custom hamburger menu. Let’s tie up everything.

Open up HomeScreen.js and edit as follows:

import React from 'react'
import { View, Text } from 'react-native'
import MyHeader from '../components/MyHeader'

const HomeScreen = props => {
  return (
    <View>
      <MyHeader navigation={props.navigation} title="Home" />
      <Text>This is Home Screen</Text>
    </View>
  )
}

export default HomeScreen

We’ve added MyHeader component and passing navigation props which we receive from react-navigation package via higher-order component which we’ve seen earlier.

Repeat the same for SettingsScreen.js:

import React from 'react'
import { View, Text } from 'react-native'

import MyHeader from '../components/MyHeader'

const SettingsScreen = props => {
  return (
    <View>
      <MyHeader navigation={props.navigation} title="Settings" />
      <Text>This is Settings Screen</Text>
    </View>
  )
}

export default SettingsScreen

Let’s reload our app and see how it looks:

alt text

Great! That looks pretty!

Android?

First thing is that, as per react-navigation document, you’ll have to modify ./android/app/src/main/java/com/drawernavigationdemo/MainActivity.java file. Refer React Navigation doc.

After running react-native run-android, I got into some issues related to the bundler. I’ve fixed it by googling around and found the following steps from somewhere:

./android/gradlew clean

react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res

Wait for some time till the bundler finishes its job. Then run react-native run-android and all will run smoothly.

Make sure your emulator is already running.

Hope this post is useful. If yes, please hit like and share it.