Search code examples
javascriptreactjsreact-nativereact-navigation-v5

Custom Drawer in react navigation


In my react native project I have custom drawer with screens like screen1 and screen2. Screen1 is used for stack navigator and in Screen 2 it contains tab navigator. How to enable this kind of nesting navigation.

I am using react navigation 5 in order to build custom drawer.

Here is my code:

  import { DrawerContentScrollView, DrawerItem } from "@react-navigation/drawer";
  .............
  render = () => {
    <DrawerContentScrollView {...props}>
    <View style={styles.menuContainer}>
    <View style={[styles.menuItemsCard, { backgroundColor: "#fff2df" }]}>
    <View style={[styles.circleContainer, { backgroundColor: "#FFC56F" }]}>
    <Icon travel name="suitcase" type="font-awesome" color="#fbae41" />
    </View>
            <DrawerItem
             label="Screen1"
             labelStyle={{ color: "#fbae41", fontSize: 10 }}
                            onPress={() => {
                                props.navigation.navigate("PatientInfo");
                            }}
                        />
            </View>
            <View style={[styles.itemCard, { backgroundColor: "#EFFFD5" }]}>
            <View style={[styles.circleContainer, { backgroundColor: "#b5ff39" }]}>
            <Icon Medical name="briefcase" type="font-awesome" color="#609806"></Icon>
            </View>
                        <DrawerItem
                            label="Screen2"
                            labelStyle={{ color: "#609806" }}
                            onPress={() => {
                                props.navigation.navigate("Diagnose");
                            }}
                        />
                    </View>
                </View>
    </DrawerContentScrollView>
  }

mainNaviagtor:

const MainNavigator = () => {
return (
    <Drawer.Navigator drawerContent={props => <Menu {...props} />} drawerStyle={{ width: 
 "100%" }}>
        <Stack.Screen name="Screen1" component={PatientInfoScreen} screenOptions={headerOptions} />
         <Stack.Screen name="Screen2" component={DiagnoseScreen} /> //Here i need tab navigator

        
    </Drawer.Navigator>
);
};

My older code: (react navigation 4.x)

createDrawerNavigator(
{
    Screen1: {
        screen: createStackNavigator(
            {
                PatientInfo: { screen: PatientInfoScreen }
            },
            headerOptions
        )
    },

    Screen2: {
        screen: createBottomTabNavigator({
            Diagnose: {
                screen: diagnoseNavigation
            },
            Causes: { screen: causeNavigation },
        })
    },
})

Output:

enter image description here

How should I solve this issue? I also referred to the https://reactnavigation.org/docs/nesting-navigators/.

Any one please help me to solve this issue.


Solution

  • Working Example: Expo Snack

    Final Output:

    enter image description here

    Full source Code:

    import * as React from 'react';
    import {
      View,
      Text,
      StyleSheet,
      useWindowDimensions,
      Button,
    } from 'react-native';
    import { NavigationContainer } from '@react-navigation/native';
    import { Feather } from '@expo/vector-icons';
    import { createStackNavigator } from '@react-navigation/stack';
    import {
      createDrawerNavigator,
      DrawerContentScrollView,
      DrawerItemList,
      DrawerItem,
    } from '@react-navigation/drawer';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    
    const Drawer = createDrawerNavigator();
    const Tab = createBottomTabNavigator();
    const Stack = createStackNavigator();
    
    function TabNav() {
      return (
        <Tab.Navigator>
          <Tab.Screen
            name="TabOne"
            component={() => (
              <View style={styles.container}>
                <Text>TabOne</Text>
              </View>
            )}
          />
          <Tab.Screen
            name="TabTwo"
            component={() => (
              <View style={styles.container}>
                <Text>TabTwo</Text>
              </View>
            )}
          />
        </Tab.Navigator>
      );
    }
    
    const StackNav = () => {
      return (
        <Stack.Navigator>
          <Stack.Screen name="Feed" component={Feed} />
          <Stack.Screen name="Article" component={Article} />
        </Stack.Navigator>
      );
    };
    
    function CustomDrawerContent(props) {
      const width = useWindowDimensions().width * 0.3;
    
      return (
        <DrawerContentScrollView {...props}>
          <View style={styles.menuContainer}>
            <View
              style={[
                styles.menuItemsCard,
                { backgroundColor: '#fff2df', width: width, height: width },
              ]}>
              <>
                <View
                  style={[styles.circleContainer, { backgroundColor: '#FFC56F' }]}>
                  <Feather travel name="briefcase" size={25} color="#fbae41" />
                  <DrawerItem
                    label="Screen1"
                    labelStyle={{ color: '#fbae41', fontSize: 10 }}
                    onPress={() => {
                      props.navigation.navigate('Screen1');
                    }}
                  />
                </View>
              </>
              <DrawerItem
                style={{
                  position: 'absolute',
                  left: 0,
                  width: width,
                  height: width,
                }}
                label="Screen2"
                labelStyle={{ color: '#609806' }}
                onPress={() => {
                  props.navigation.navigate('Screen1');
                }}
              />
            </View>
            <View
              style={[
                styles.menuItemsCard,
                { backgroundColor: '#EFFFD5', width: width, height: width },
              ]}>
              <View
                style={[styles.circleContainer, { backgroundColor: '#b5ff39' }]}>
                <Feather Medical name="briefcase" size={25} color="#609806" />
              </View>
    
              <DrawerItem
                style={{
                  position: 'absolute',
                  left: 0,
                  width: width,
                  height: width,
                }}
                label="Screen2"
                labelStyle={{ color: '#609806' }}
                onPress={() => {
                  props.navigation.navigate('StackNav');
                }}
              />
            </View>
          </View>
        </DrawerContentScrollView>
      );
    }
    
    function MyDrawer() {
      return (
        <Drawer.Navigator
          drawerContent={(props) => <CustomDrawerContent {...props} />}>
          <Drawer.Screen name="Screen1" component={StackNav} />
          <Drawer.Screen name="StackNav" component={TabNav} />
        </Drawer.Navigator>
      );
    }
    
    export default function App() {
      return (
        <NavigationContainer>
          <MyDrawer />
        </NavigationContainer>
      );
    }
    
    function Feed({ navigation }) {
      return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Text>Feed Screen</Text>
          <Button
            title={'Article'}
            onPress={() => navigation.navigate('Article')}
          />
        </View>
      );
    }
    
    function Article({ navigation }) {
      return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
          <Text>Article Screen</Text>
          <Button title={'Feed'} onPress={() => navigation.navigate('Feed')} />
        </View>
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
      },
      menuContainer: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'space-evenly',
      },
      menuItemsCard: {
        flexDirection: 'column',
        justifyContent: 'center',
        alignItems: 'center',
        borderRadius: 10,
      },
      circleContainer: {
        width: 50,
        height: 50,
        borderRadius: 25,
        padding: 10,
      },
    });