How to Create a Drawer Navigator with Custom Component in React Native using React Navigation

In this blog post I will walk you through how to create a navigation drawer with custom content component in react native using navigation library react navigation.

First of all add react navigation library to your react native project using the following command:

npm install react-navigation

Now, install react native gesture handler in your project using the command:

npm install react-native-gesture-handler

As I am using react native version greater than 0.60, I don’t need to link react native gesture handler manually. In case of ios, make sure cocoapods installed and run the following commands:

cd ios
pod install
cd ..

As a last step of installation, do following changes in your MainActivity.java file as given below.

package com.reactnavigation.example;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;//add
import com.facebook.react.ReactRootView;//add
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;//add 

public class MainActivity extends ReactActivity {

  @Override
  protected String getMainComponentName() {
    return "Example";
  }


  @Override //add
  protected ReactActivityDelegate createReactActivityDelegate() { //add
    return new ReactActivityDelegate(this, getMainComponentName()) { //add
     @Override //add
     protected ReactRootView createRootView() { //add
       return new RNGestureHandlerEnabledRootView(MainActivity.this); //add
      } //add
   }; //add
  } //add
}

That’s all needed for the proper installation of react navigation library. If you have doubts then refer the official documentation of react navigation library.

Before coming into code, add a folder named src in your root project and create two JavaScript files named Home ,Details and CustomComponent.js. These Home and Details would be the menus inside navigation drawer.

Now, you need both stack navigator and drawer navigator for this example. We include the stack navigator inside the drawer navigator. Following is the code of App.js file.

import React from 'react';
import {
  createStackNavigator,
  createDrawerNavigator,
  createAppContainer,
} from "react-navigation";
import Home from "./src/Home";
import Details from "./src/Details";
import CustomComponent from "./src/CustomComponent";

const entry = createStackNavigator({
  Home,
  Details
});

const drawer = createDrawerNavigator(
  {
    entry,
  },
  {
    contentComponent: props => <CustomComponent {...props} />,
  }
);
const App = createAppContainer(drawer);
export default App;

We use createStackNavigator for creating stack navigator whereas createDrawerNavigator is used to create drawer navigator. createAppContainer is used to wrap the navigator. As you noticed we have used contentComponent prop to add our custom design to the navigator.

Here’s the code of CustomComponent.js

import React, { Component } from "react";
import {
  View,
  Text,
  StyleSheet,
  Image,
  TouchableOpacity,
  Platform,
} from "react-native";

export default class CustomComponent extends Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    const { navigate } = this.props.navigation;
    return (
      <View style={styles.container}>
        <View style={styles.containertopRow}>
          <Image
            style={styles.imageTopRow}
            source={{
              uri:
                'https://cdn.pixabay.com/photo/2014/04/05/12/20/man-316917_960_720.jpg',
            }}
          />
        </View>
        <View style={styles.containerBottom}>
          <TouchableOpacity
            onPress={() => navigate('Home')}
            style={styles.containerBottomItem}
          >
            <View style={styles.button}>
              <Text style={styles.txtBottom}>Home</Text>
            </View>
          </TouchableOpacity>

          <TouchableOpacity
            onPress={() => navigate('Details')}
            style={styles.containerBottomItem}
          >
            <View style={styles.button}>
              <Text style={styles.txtBottom}>Details</Text>
            </View>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#17BED0'
  },
  containertopRow: {
    marginTop: 10,
    marginLeft: 10,
    justifyContent: "center",
    alignItems: 'center'
  },
  txtBottom: {
    marginLeft: 10,
    color: '#E6FAFF',
    fontSize: 15,
    fontWeight: '100'
  },
  imageTopRow: {
    height: 80,
    width: 80,
    ...Platform.select({
      ios: {
        borderRadius: 80 / 2
      },
      android: {
        borderRadius: 80
      }
    })
  },
  icon: {
    height: 25,
    width: 25,
    marginRight: 10
  },
  button: {
    alignItems: 'center',
    flexDirection: 'row',
    justifyContent: 'flex-start'
  },

  containertopRowText: {
    flexDirection: 'column',
    marginLeft: 5
  },

  containerBottom: {
    backgroundColor: '#17BED0'
  },
  containerBottomItem: {
    padding: 10,
    alignItems: 'center',
    flexDirection: 'row',
    justifyContent: 'flex-start',
    borderBottomColor: '#E6FAFF',
    borderBottomWidth: 0.5
  }
});

In custom component I have an image at the top and the menus such as Home and Details are placed below that. When menu are clicked they are navigated to corresponding screens. As you noted, this is a fully customised navigation menu.

Here’s the code of Home.js:

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';

export default class Home extends Component {
  static navigationOptions = ({ navigation }) => ({
    headerStyle: {
      backgroundColor: '#13C0CE',
    },
    headerLeft: (
      <View>
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Image
            style={{ marginLeft: 10, height: 25, width: 25 }}
            source={require('../images/menu.png')}
          />
        </TouchableOpacity>
      </View>
    ),
  });
  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text style={{ fontSize: 20 }}> Home </Text>
      </View>
    );
  }
}

In home, I have added a hamburger icon as image. When the image is clicked navigation drawer gets opened with navigation.openDrawer(). Code of the Details.js is almost same as Home.js.

Here’s the code of Details.js:

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, Image } from 'react-native';

export default class Details extends Component {
  static navigationOptions = ({ navigation }) => ({
    headerStyle: {
      backgroundColor: "#13C0CE"
    },
    headerLeft: (
      <View>
        <TouchableOpacity onPress={() => navigation.openDrawer()}>
          <Image
            style={{ marginLeft: 10, height: 25, width: 25 }}
            source={require("../images/menu.png")}
          />
        </TouchableOpacity>
      </View>
    )
  });

  constructor(props) {
    super(props);
    this.state = {};
  }

  render() {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text style={{ fontSize: 20 }}> Details </Text>
      </View>
    );
  }
}

The output of navigation drawer in react native will be as given below:

1 thought on “How to Create a Drawer Navigator with Custom Component in React Native using React Navigation”

Leave a Reply

%d bloggers like this: