Dynamically Set Drawer/Sidebar Options in React Navigation Drawer

Dynamic React Navigation Drawer Options

In this post, I am going to share how to dynamically set drawer/sidebar options in React Navigation Drawer. We will use react-navigation to create a Navigation Drawer structure and going to use a custom navigation drawer instead of a default drawer. Dynamically set drawer/sidebar options in React Navigation is a very important example for those guys who have a user login as well as guest login in their application. There are also many scenarios where you need to set the drawer options dynamically.

It is better to see React Native Navigation Drawer first if you are not aware of how to create a React Navigation Drawer? and if you know that then you can also see Custom Navigation Drawer / Sidebar with Image and Icon in Menu Options as this is an extended post it.

Why do We Need to Set Drawer/Sidebar Options Dynamically?

As I already mentioned this is a very important example for many of the developers. There are many cases where you need to set the dynamic options in the sidebar, here are 3 to 4 cases which I want to share with you:

  1. Suppose your application has a user login as well as guest login for which you want to set the drawer options dynamically
  2. You have a multi-language application and you need to change the option labels in runtime
  3. You want to show the drawer navigation options on the basis of user permission
  4. If you have an E-Commerce application and you have listed categories in the sidebar you need to change the same on the basis of selection.

How to Set Drawer/Sidebar Options Dynamically?

If you create a basic navigation drawer you will get a default sidebar/drawer coming from the left and will have the same options listed in the sidebar/drawer which you have mentioned in your Drawer Navigator. For example, if you have created the below Drawer Navigator then you will see two options in the sidebar/drawer with the label 'Home Screen' and 'Setting Screen'

const DrawerNavigationRoutes = createDrawerNavigator({
  HomeScreen: {
    screen: FirstActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Home Screen',
    },
  },
  SettingsScreen: {
    screen: SecondActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Setting Screen',
    },
  }
},

but if you want to set the navigation sidebar/drawer options dynamically you need to create a custom drawer. Creating or updating your existing default navigation drawer to custom navigation drawer very easy in React Navigation, you just need to add some line of code to replace the default drawer with your custom drawer.

Custom Navigation Drawer

To replace default navigation drawer with your custom drawer you need to provide contentComponent, drawerOpenRoute, drawerCloseRoute, drawerToggleRoute. Below is the code snippet which is having the necessary changes

const DrawerNavigationRoutes = createDrawerNavigator({
  HomeScreen: {
    screen: FirstActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Home Screen',
    },
  },
  SettingsScreen: {
    screen: SecondActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Setting Screen',
    },
  }
},
{
    contentComponent: CustomSidebarMenu,
    drawerOpenRoute: 'DrawerOpen',
    drawerCloseRoute: 'DrawerClose',
    drawerToggleRoute: 'DrawerToggle'
});

Here CustomSidebarMenu is the React Native custom component which we will create and will pass here so that it will replace the default navigation drawer.

Just imagine CustomSidebarMenu component as an independent screen that will not cover the whole screen instead it will cover the screen equal to the width of the navigation drawer.

In that component, we will create a header and a list using loop:

  1. The header will be for the name of the user which is just to give you some idea about the custom drawer possibilities
  2. List with some items, on click of these items we will navigate the user to the desired screen

Making Custom Navigation Drawer options Dynamic

As I said we will have a list of items in CustomSidebarMenu as options of the navigation drawer, which means now we have full control over the drawer options. To create the navigation option dynamic we will use this list and will set up a State in a way that whenever we change the State it will change the list in navigation drawer. This is how we can set the custom drawer options dynamic.

Dynamic React Navigation Drawer Options Example Overview

In the example, we are going to create a login screen that will have two buttons ‘User Login’ and ‘Guest Login’. On click of these buttons, the user/guest will navigate to the home screen with some additions params which we will pass internally. Once user/guest land on the Home Screen we will receive our props in the CustomSidebarMenu and will set the loginAs State. Setting loginAs State will help us to decide which Option list we have to set in the custom navigation drawer.

After all this explanation I hope you understand what we are going to create, so without any delay let’s start with the example.

To Make a React Native App

Getting started with React Native will help you to know more about the way you can make a React Native project. We are going to use react-native init to make our React Native App. Assuming that you have node installed, you can use npm to install the react-native-cli command line utility. Open the terminal and go to the workspace and run

npm install -g react-native-cli

Run the following commands to create a new React Native project

react-native init ProjectName

If you want to start a new project with a specific React Native version, you can use the --version argument:

react-native init ProjectName --version X.XX.X
react-native init ProjectName --version react-native@next

This will make a project structure with an index file named App.js in your project directory.

Installation of Dependencies

To install the dependencies open the terminal and jump into your project

cd ProjectName

1. Install react-navigation dependency to import createAppContainer

npm install react-navigation --save

2. Other supporting libraries for react-navigation

npm install react-native-gesture-handler react-native-safe-area-context @react-native-community/masked-view react-native-screens react-native-reanimated --save

3. Install react-navigation-drawer to import createDrawerNavigator

npm install react-navigation-drawer --save

4. Install react-navigation-stack to import createStackNavigator

npm install react-navigation-stack --save

These commands will copy all the dependencies into your node_module directory.

CocoaPods Installation

Please use the following command to install CocoaPods

cd ios && pod install && cd ..

Project Structure

To start with this example you need to create a directory named Screen and two directories under that with the name Components and drawerScreens. Now create Screen/LoginScreen.js, Screen/Components/CustomSidebarMenu.js, Screen/Components/NavigationDrawerHeader.js, Screen/drawerScreens/HomeScreen.js, and Screen/drawerScreens/SettingsScreen.js

Drawer Dynamic Value Structure

Code for Dynamic React Navigation Drawer Options

Now Open App.js in any code editor and replace the code with the following code

App.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

import React from 'react';

//Import Navigators from React Navigation
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { createDrawerNavigator} from 'react-navigation-drawer';

//Import External Screens
import LoginScreen from './Screen/LoginScreen';
import HomeScreen from './Screen/drawerScreens/HomeScreen';
import SettingsScreen from './Screen/drawerScreens/SettingsScreen';
import CustomSidebarMenu from './Screen/Components/CustomSidebarMenu';
import NavigationDrawerHeader from './Screen/Components/NavigationDrawerHeader';

const FirstActivity_StackNavigator = createStackNavigator({
  First: {
    screen: HomeScreen,
    navigationOptions: ({ navigation }) => ({
      title: 'Home Screen',
      headerLeft: ()=> <NavigationDrawerHeader navigationProps={navigation} />,
      headerStyle: {
        backgroundColor: '#307ecc',
      },
      headerTintColor: '#fff',
    }),
  },
});

const SecondActivity_StackNavigator = createStackNavigator({
  First: {
    screen: SettingsScreen,
    navigationOptions: ({ navigation }) => ({
      title: 'Setting Screen',
      headerLeft: ()=> <NavigationDrawerHeader navigationProps={navigation} />,
      headerStyle: {
        backgroundColor: '#307ecc',
      },
      headerTintColor: '#fff',
    }),
  },
});

const DrawerNavigationRoutes = createDrawerNavigator({
  HomeScreen: {
    screen: FirstActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Home Screen',
    },
  },
  SettingsScreen: {
    screen: SecondActivity_StackNavigator,
    navigationOptions: {
      drawerLabel: 'Setting Screen',
    },
  }
},
{
    contentComponent: CustomSidebarMenu,
    drawerOpenRoute: 'DrawerOpen',
    drawerCloseRoute: 'DrawerClose',
    drawerToggleRoute: 'DrawerToggle'
});

const App = createStackNavigator({
  //Stack Navigator for Login and Sign up Screen
  LoginScreen: {
    screen: LoginScreen,
    navigationOptions: {
      title: 'Demo Login',
      headerStyle: {
        backgroundColor: '#307ecc',
      },
      headerTintColor: '#fff',
    },
  },
  DrawerNavigationRoutes: {
    screen: DrawerNavigationRoutes,
    navigationOptions: {
      headerShown: false,
    },
  },
});
export default createAppContainer(App);

Open Screen/LoginScreen.js in any code editor and replace the code with the following code.

LoginScreen.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

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

// Creating Login Screen
const LoginScreen = props => {
  return (
    <View style={styles.mainBody}>
      <View style={{ alignItems: 'center' }}>
        {/* <Image
          source={require('../Image/aboutreact.png')}
          style={{
            width: '50%',
            height: 100,
            resizeMode: 'contain',
            margin: 30,
          }}
        /> */}
        <Text
          style={{
            fontSize: 40,
            color: 'white',
            fontWeight: 'bold',
            paddingVertical: 20,
          }}>
          AboutReact
        </Text>
      </View>
      <TouchableOpacity
        style={styles.buttonStyle}
        activeOpacity={0.5}
        onPress={() =>
          props.navigation.navigate('DrawerNavigationRoutes', { login: 'user' })
        }>
        <Text style={styles.buttonTextStyle}>User LOGIN</Text>
      </TouchableOpacity>
      <TouchableOpacity
        style={styles.buttonStyle}
        activeOpacity={0.5}
        onPress={() =>
          props.navigation.navigate('DrawerNavigationRoutes', {
            login: 'guest',
          })
        }>
        <Text style={styles.buttonTextStyle}>LOGIN as a Guest</Text>
      </TouchableOpacity>
    </View>
  );
};
export default LoginScreen;

const styles = StyleSheet.create({
  mainBody: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor: '#307ecc',
  },
  buttonStyle: {
    backgroundColor: '#7DE24E',
    borderWidth: 0,
    color: '#FFFFFF',
    borderColor: '#7DE24E',
    height: 40,
    alignItems: 'center',
    borderRadius: 30,
    marginLeft: 35,
    marginRight: 35,
    marginTop: 20,
    marginBottom: 20,
  },
  buttonTextStyle: {
    color: '#FFFFFF',
    paddingVertical: 10,
    fontSize: 16,
  },
});

Open Screen/drawerScreens/HomeScreen.js in any code editor and replace the code with the following code.

HomeScreen.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

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

const HomeScreen = () => {
  global.currentScreenIndex = 'HomeScreen';
  return (
    <View style={{ flex: 1, alignItems: 'center', marginTop: 100 }}>
      <Text style={{ fontSize: 23, marginTop: 10 }}>Home Screen</Text>
      <Text style={{ fontSize: 18, marginTop: 10 }}>
        Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer
      </Text>
      <Text style={{ fontSize: 18, marginTop: 10 }}>
        
Home
</Text> </View> ); }; export default HomeScreen;

Open Screen/drawerScreens/SettingsScreen.js in any code editor and replace the code with the following code.

SettingsScreen.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

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

const SettingsScreen = () => {
  return (
    <View style={{ flex: 1, alignItems: 'center', marginTop: 100 }}>
      <Text style={{ fontSize: 23, marginTop: 10 }}>Setting Screen</Text>
      <Text style={{ fontSize: 18, marginTop: 10 }}>
        Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer
      </Text>
      <Text style={{ fontSize: 18, marginTop: 10 }}>
        
Home
</Text> </View> ); }; export default SettingsScreen;

Open Screen/Components/CustomSidebarMenu.js in any code editor and replace the code with the following code.

CustomSidebarMenu.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

import React, { useEffect, useState } from 'react';
import { View, StyleSheet, Text } from 'react-native';

const CustomSidebarMenu = props => {
  let [loginAs, setLoginAs] = useState('');

  useEffect(() => {
    setLoginAs(props.navigation.getParam('login', 'defaultValue'));
  }, []);

  let itemsUser = [
    {
      navOptionName: 'User Home Screen',
      screenToNavigate: 'HomeScreen',
    },
    {
      navOptionName: 'User Setting Screen',
      screenToNavigate: 'SettingsScreen',
    },
    {
      navOptionName: 'Change Options for the Guest',
      screenToNavigate: 'ChangeOptionGuest',
    },
    {
      navOptionName: 'Logout',
      screenToNavigate: 'logout',
    },
  ];

  let itemsGuest = [
    {
      navOptionName: 'Guest Home Screen',
      screenToNavigate: 'HomeScreen',
    },
    {
      navOptionName: 'Guest Setting Screen',
      screenToNavigate: 'SettingsScreen',
    },
    {
      navOptionName: 'Change Options for the User',
      screenToNavigate: 'ChangeOptionUser',
    },
    {
      navOptionName: 'Logout',
      screenToNavigate: 'logout',
    },
  ];

  const handleClick = (index, screenToNavigate) => {
    if (screenToNavigate == 'logout') {
      props.navigation.toggleDrawer();
      props.navigation.navigate('LoginScreen');
    } else if (screenToNavigate == 'ChangeOptionGuest') {
      props.navigation.toggleDrawer();
      setLoginAs('guest');
    } else if (screenToNavigate == 'ChangeOptionUser') {
      props.navigation.toggleDrawer();
      setLoginAs('user');
    } else {
      props.navigation.toggleDrawer();
      global.currentScreenIndex = screenToNavigate;
      props.navigation.navigate(screenToNavigate);
    }
  };
  return (
    <View style={stylesSidebar.sideMenuContainer}>
      <View style={stylesSidebar.profileHeader}>
        <View style={stylesSidebar.profileHeaderPicCircle}>
          <Text style={{ fontSize: 25, color: '#307ecc' }}>
            {'About React'.charAt(0)}
          </Text>
        </View>
        <Text style={stylesSidebar.profileHeaderText}>AboutReact</Text>
      </View>
      <View style={stylesSidebar.profileHeaderLine} />
      <View style={{ width: '100%', flex: 1 }}>
        {(loginAs === 'user' ? itemsUser : itemsGuest).map((item, key) => (
          <View
            style={{
              flexDirection: 'row',
              alignItems: 'center',
              padding: 20,
              color: 'white',
              backgroundColor:
                global.currentScreenIndex === item.screenToNavigate
                  ? '#4b9ff2'
                  : '#307ecc',
            }}
            key={key}
            onStartShouldSetResponder={() =>
              handleClick(key, item.screenToNavigate)
            }>
            <Text style={{ fontSize: 15, color: 'white' }}>
              {item.navOptionName}
            </Text>
          </View>
        ))}
      </View>
    </View>
  );
};

const stylesSidebar = StyleSheet.create({
  sideMenuContainer: {
    width: '100%',
    height: '100%',
    backgroundColor: '#307ecc',
    paddingTop: 40,
    color: 'white',
  },
  profileHeader: {
    flexDirection: 'row',
    backgroundColor: '#307ecc',
    padding: 15,
    textAlign: 'center',
  },
  profileHeaderPicCircle: {
    width: 60,
    height: 60,
    borderRadius: 60 / 2,
    color: 'white',
    backgroundColor: '#ffffff',
    textAlign: 'center',
    justifyContent: 'center',
    alignItems: 'center',
  },
  profileHeaderText: {
    color: 'white',
    alignSelf: 'center',
    paddingHorizontal: 10,
    fontWeight: 'bold',
  },
  profileHeaderLine: {
    height: 1,
    marginHorizontal: 20,
    backgroundColor: '#e2e2e2',
    marginTop: 15,
    marginBottom: 10,
  }
});
export default CustomSidebarMenu;

Open Screen/Components/NavigationDrawerHeader.js in any code editor and replace the code with the following code.

NavigationDrawerHeader.js

/*Example to Dynamically Change Drawer/Sidebar Options in React Navigation Drawer */
/* https://aboutreact.com/dynamically-change-sidebar-options/ */

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

const NavigationDrawerHeader = props => {
  const toggleDrawer = () => {
    props.navigationProps.toggleDrawer();
  };

  return (
    <View style={{ flexDirection: 'row' }}>
      <TouchableOpacity onPress={toggleDrawer}>
        <Image
          source={{
            uri:
              'https://raw.githubusercontent.com/AboutReact/sampleresource/master/drawerWhite.png',
          }}
          style={{ width: 25, height: 25, marginLeft: 5 }}
        />
      </TouchableOpacity>
    </View>
  );
};
export default NavigationDrawerHeader;

To Run the React Native App

Open the terminal again and jump into your project using.
cd ProjectName
To run the project on an Android Virtual Device or on real debugging device
react-native run-android
or on the iOS Simulator by running
react-native run-ios (macOS only).

Output Screenshots

Drawer Dynamic Value 1   Drawer Dynamic Value 2   Drawer Dynamic Value 3

This is how you can Dynamically set drawer/sidebar options in React Navigation Drawer. If you have any doubts or you want to share something about the topic you can comment below or contact us here. There will be more posts coming soon. Stay tuned!

Hope you liked it. 🙂


Related Posts

2 thoughts on “Dynamically Set Drawer/Sidebar Options in React Navigation Drawer”

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.