React native drawer navigation with stack navigator - react-native

I'm trying to develop an app to understand the react native basics. I'm usin react navigation and I would like to see menu in every page of my app. I've developed someting like;
-StackNavigtor
-Login Screen
-DrawerNagivation
-Screen1
-Screen2
However, inner drawer's components can not benefit from the stacking feature. What's the best way of obtaining drawer navigation with stack navigator in order to obtain menu in every page of my app.
Thanks.

Yes you can follow the following step.
App.js
import React, {Component} from 'react';'
import {Platform, StyleSheet, Text, View} from 'react-native';
import { createStackNavigator } from 'react-navigation';
import Login from './src/authScreen/login/Login';
import DrawerNavigator from './src/navigation/drawerNavigation/DrawerNavigator';
export default class App extends Component{
render() {
return (
<AppStackNavigator />
);
}
}
const AppStackNavigator = createStackNavigator({
Login:{
screen:Login
},
DrewerNav:{
screen:DrawerNavigator
}
},
navigationOptions={
headerMode:'none'
})
then create src folder and create DrawerNavigator.js . and Enter the following code.
import React from 'react' import { StyleSheet, Text, View, SafeAreaView, ScrollView, Dimensions, Image} from 'react-native';
import { createDrawerNavigator, DrawerItems } from 'react-navigation';
import Icon from 'react-native-vector-icons/FontAwesome5';import DrawerScreen1
from '../../screens/drawerScreen/DrawerScreen1' import DrawerScreen2
from '../../screens/drawerScreen/DrawerScreen2' import DrawerScreen3
from '../../screens/drawerScreen/DrawerScreen3' // import { Right }
from 'native-base';
const CustomDrawerComponent = (props)=>( <SafeAreaView>
<View style={{height:150, backgroundColor:'white', alignItems:'center', justifyContent:'center'}}>
<Image source={require('../../Images/user.jpg')} style={{height:120, width:120, borderRadius:60}} />
</View>
<ScrollView>
<DrawerItems {...props} />
</ScrollView> </SafeAreaView> )
export default createDrawerNavigator(>
DrawerScreen1: {
screen: DrawerScreen1,
navigationOptions: {
drawerLabel: 'DrawerScreen1',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} },
DrawerScreen2: {
screen: DrawerScreen2,
navigationOptions: {
drawerLabel: 'DrawerScreen2',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} },
DrawerScreen3: {
screen: DrawerScreen3,
navigationOptions: {
drawerLabel: 'DrawerScreen3',
drawerIcon: ({ tintColor }) => <Icon name="user-circle" size={17} />,
} }, }, { drawerPosition :"right", contentComponent:CustomDrawerComponent
});
Here CustomDrawerComponent add a Drawer Icon.
and add the login.js
import React, { Component } from 'react';
import {View,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import { Container, Header, Content, Button, Text } from 'native-base';
class Login extends Component{
constructor(props){
super(props);
}
loginHandler=()=>{
this.props.navigation.navigate('DrewerNav')
}
render(){
return(
<View style={styles.container}>
<Text> Login </Text>
<View style={{alignItems:'center'}}>
<Button onPress={this.loginHandler}>
<Text>Click Me!</Text>
</Button>
</View>
</View>
)
}
}
export default Login;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Further more: you can refer https://github.com/ChanakaUOMIT/React-Native-Root-boiler-plate/tree/master this project.. here also add Stack navigation, Tab Navigation and Drawer navigation in one project.

import 'react-native-gesture-handler';
import * as React from 'react';
import {View, TouchableOpacity, Image} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createDrawerNavigator} from '#react-navigation/drawer';
import LoginPage from './src/pages/LoginPage';
import SecondPage from './src/pages/SecondPage';
import ThirdPage from './src/pages/ThirdPage';
// Import Custom Sidebar
import CustomSidebarMenu from './src/pages/CustomSidebarMenu';
import SignUpPage from './src/pages/SignUp';
import Home from './src/pages/Home';
import VendingMachineList from './src/pages/VendingMachineList';
import ProductList from './src/pages/ProductList';
import ProductDetails from './src/pages/ProductDetails';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const NavigationDrawerStructure = (props) => {
//Structure for the navigatin Drawer
const toggleDrawer = () => {
//Props to open/close the drawer
props.navigationProps.toggleDrawer();
};
return (
<View style={{flexDirection: 'row'}}>
<TouchableOpacity onPress={toggleDrawer}>
<Image
source={require('./src/assets/image/Vector.png')}
style={{width: 30, height: 20, marginLeft: 5}}
/>
</TouchableOpacity>
<TouchableOpacity onPress={toggleDrawer}>
<Image
source={require('./src/assets/image/track-fresh.png')}
style={{width: 30, height: 20, marginLeft: 5}}
/>
</TouchableOpacity>
</View>
);
};
function firstScreenStack({navigation}) {
return (
<Stack.Navigator initialRouteName="LoginPage">
<Stack.Screen
name="LoginPage"
component={LoginPage}
options={{
title: 'First Page', //Set Header Title
headerLeft: () => (
<NavigationDrawerStructure
navigationProps={navigation}
/>
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerShown:false,
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
<Stack.Screen
name="SignUpPage"
component={SignUpPage}
options={{
title: 'First Page', //Set Header Title
headerLeft: () => (
<NavigationDrawerStructure
navigationProps={navigation}
/>
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerShown:false,
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}
/>
</Stack.Navigator>
);
}
function HomeStack({navigation}) {
return (
<Stack.Navigator
initialRouteName="VendingMachineList"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: {
backgroundColor: '#fff', //Set Header color
},
headerTintColor: '#000', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}>
<Stack.Screen
name="HomePage"
component={Home}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ProductList"
component={ProductList}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ProductDetails"
component={ProductDetails}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="VendingMachineList"
component={VendingMachineList}
options={{
title: '', headerShown:false, //Set Header Title
}}
/>
<Stack.Screen
name="ThirdPage"
component={ThirdPage}
options={{
title: 'Third Page', //Set Header Title
}}
/>
</Stack.Navigator>
);
}
function secondScreenStack({navigation}) {
return (
<Stack.Navigator
initialRouteName="SecondPage"
screenOptions={{
headerLeft: () => (
<NavigationDrawerStructure navigationProps={navigation} />
),
headerStyle: {
backgroundColor: '#f4511e', //Set Header color
},
headerTintColor: '#fff', //Set Header text color
headerTitleStyle: {
fontWeight: 'bold', //Set Header text style
},
}}>
<Stack.Screen
name="SecondPage"
component={SecondPage}
options={{
title: 'Second Page', //Set Header Title
}}
/>
<Stack.Screen
name="ThirdPage"
component={ThirdPage}
options={{
title: 'Third Page', //Set Header Title
}}
/>
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator
drawerContentOptions={{
activeTintColor: '#e91e63',
itemStyle: {marginVertical: 5},
}}
drawerContent={(props) => <CustomSidebarMenu {...props} />}>
<Drawer.Screen
name="LoginPage"
options={{drawerLabel: 'First page Option',swipeEnabled:false}}
component={firstScreenStack}
/>
<Drawer.Screen
name="Home"
options={{drawerLabel: 'Second page Option'}}
component={HomeStack}
/>
<Drawer.Screen
name="SecondPage"
options={{drawerLabel: 'Second page Option'}}
component={secondScreenStack}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}
export default App;

Related

React native (React navigation)- instance of same screen in differents tabs. Navigate from drawer

I have an issue with react navigation.
I would like to have the same behavior as the linkedIn app has.
I mean, in that app, you can open the settings page from the drawer in differents tabs. You can open it from the first tab, second one... and so on. and at the end you get multiple instances.
I am not able to reproduce this behavior
My navigation is:
One drawer with one drawer screen (one Tab navigator inside). 3 tabs screens inside that Tab navigator. Each one contains a stack. I have set the same screens in that screen. For example I want to share the Profile, so I have one profile screen in each tab.
In the customDrawer I navigate to screens name, but here is the problem. React navigation does not know what stack should call before calling the right screen.
And I cannot find a way to know the current mounted stack so I cannot set it dinamically in order to do inside the custom drawer:
onPress={() =>
props.navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.SETTINGS })
}
Thanks!
App.tsx
/* eslint-disable react-native/no-inline-styles */
import 'react-native-gesture-handler';
import React from 'react';
import { Text } from 'react-native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import {
createDrawerNavigator,
DrawerContentScrollView,
DrawerItem,
} from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import { QueryClient, QueryClientProvider } from '#tanstack/react-query';
import { StatusBar } from 'expo-status-bar';
import HomeStackScreen from '#pages/Home';
import { Routes } from '#src/constants/routes';
import { PracticalStackScreen } from '#src/pages/Practical/Practical';
import { TheoryStackScreen } from '#src/pages/Theory/Theory';
// Create a client
const queryClient = new QueryClient();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator
screenOptions={{ headerShown: false }}
initialRouteName={Routes.student.home.STACK}
>
<Tab.Screen
name={Routes.student.theory.STACK}
component={TheoryStackScreen}
options={{ title: 'TEÓRICO' }}
/>
<Tab.Screen
name={Routes.student.home.STACK}
component={HomeStackScreen}
options={{ title: '' }}
/>
<Tab.Screen
name={Routes.student.practical.STACK}
component={PracticalStackScreen}
options={{ title: 'PRÁCTICO' }}
/>
</Tab.Navigator>
);
};
function CustomDrawerContent(props: any) {
console.log('props ', props);
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(Routes.student.SETTINGS)}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(Routes.student.PAYMENT)}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(Routes.student.PROFILE)}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(Routes.student.FAQ)}
/>
<DrawerItem
label='Atención al alumno'
onPress={() => props.navigation.navigate(Routes.student.STUDENT_SUPPORT)}
/>
</DrawerContentScrollView>
);
}
const DrawerNavigation = () => {
return (
<Drawer.Navigator
useLegacyImplementation={true}
drawerContent={(props) => <CustomDrawerContent {...props} />}
initialRouteName={Routes.student.home.STACK}
>
<Drawer.Screen name={Routes.MAIN_TAB} component={TabNavigator} />
</Drawer.Navigator>
);
};
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<StatusBar />
<NavigationContainer>
<DrawerNavigation />
</NavigationContainer>
</QueryClientProvider>
);
}
Home.tsx
/* eslint-disable react-native/no-color-literals */
import React from 'react';
import { StyleSheet, Text, View, Pressable } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const HomeStack = createNativeStackNavigator();
export const HomeStackScreen = (): JSX.Element => {
return (
<HomeStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<HomeStack.Screen name={Routes.student.home.MAIN} component={Home} />
<HomeStack.Screen name={Routes.student.PROFILE} component={Profile} />
<HomeStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<HomeStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<HomeStack.Screen name={Routes.student.FAQ} component={Faq} />
<HomeStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</HomeStack.Navigator>
);
};
export const Home = ({ navigation }: any): JSX.Element => (
<View style={styles.container}>
<Text>Home Screen</Text>
<Pressable style={styles.button} onPress={() => navigation.navigate(Routes.student.PROFILE)}>
<Text style={styles.text}>Perfil</Text>
</Pressable>
</View>
);
const backgroundColor = '#fff';
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: 'grey',
borderRadius: 4,
elevation: 3,
justifyContent: 'center',
paddingHorizontal: 32,
paddingVertical: 12,
},
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
text: {
color: 'white',
fontSize: 16,
fontWeight: 'bold',
letterSpacing: 0.25,
lineHeight: 21,
},
});
Theroy.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const TheoryStack = createNativeStackNavigator();
export const TheoryStackScreen = (): JSX.Element => {
return (
<TheoryStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<TheoryStack.Screen name={Routes.student.theory.MAIN} component={Theory} />
<TheoryStack.Screen name={Routes.student.PROFILE} component={Profile} />
<TheoryStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<TheoryStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<TheoryStack.Screen name={Routes.student.FAQ} component={Faq} />
<TheoryStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</TheoryStack.Navigator>
);
};
export function Theory({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Theory Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Practical'
onPress={() => navigation.navigate(Routes.student.practical.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Practical.tsx
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { Routes } from '#src/constants/routes';
import Faq from '../Faq';
import Payment from '../Payment';
import Profile from '../Profile';
import Settings from '../Settings';
import StudentSupport from '../StudentSupport';
const PracticalStack = createNativeStackNavigator();
export const PracticalStackScreen = (): JSX.Element => {
return (
<PracticalStack.Navigator
screenOptions={{ headerStyle: { backgroundColor: 'red' }, headerShown: false }}
>
<PracticalStack.Screen name={Routes.student.practical.MAIN} component={Practical} />
<PracticalStack.Screen name={Routes.student.PROFILE} component={Profile} />
<PracticalStack.Screen name={Routes.student.SETTINGS} component={Settings} />
<PracticalStack.Screen name={Routes.student.PAYMENT} component={Payment} />
<PracticalStack.Screen name={Routes.student.FAQ} component={Faq} />
<PracticalStack.Screen name={Routes.student.STUDENT_SUPPORT} component={StudentSupport} />
</PracticalStack.Navigator>
);
};
export function Practical({ navigation }: any): JSX.Element {
return (
<View style={styles.container}>
<Text>Practical Screen</Text>
<Button title='Go to Home' onPress={() => navigation.navigate(Routes.student.home.STACK)} />
<Button
title='Go to Theory'
onPress={() => navigation.navigate(Routes.student.theory.STACK)}
/>
<Button
title='Go to Profile'
onPress={() =>
navigation.navigate(Routes.student.home.STACK, { screen: Routes.student.PROFILE })
}
/>
</View>
);
}
const backgroundColor = '#fff';
const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor,
flex: 1,
justifyContent: 'center',
},
});
Try renaming your Settings screen component differently for each stack navigator. So something like
<PracticalStack.Screen name="Practical/Settings" component={Settings} />
<HomeStack.Screen name="Home/Settings" component={Settings} />
Then you could navigate to the appropriate screen from your drawer based on the tab in focus.
I think I found a possible solution to my question. I have changed the CustomDrawerContent.
function CustomDrawerContent(props: any) {
const drawerState = props.state.routes[0]?.state;
const routeIndex = drawerState?.index;
const focusedTab = drawerState?.routes?.[routeIndex]?.name || Routes.student.home.STACK;
return (
<DrawerContentScrollView {...props}>
<Text>Mi cuenta</Text>
<DrawerItem
label='Configuración'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.SETTINGS })}
/>
<DrawerItem
label='Métodos de pago'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PAYMENT })}
/>
<Text>Social</Text>
<DrawerItem
label='Tiktok'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.PROFILE })}
/>
<Text>Ayuda</Text>
<DrawerItem
label='Preguntas frecuentes'
onPress={() => props.navigation.navigate(focusedTab, { screen: Routes.student.FAQ })}
/>
<DrawerItem
label='Atención al alumno'
onPress={() =>
props.navigation.navigate(focusedTab, { screen: Routes.student.STUDENT_SUPPORT })
}
/>
</DrawerContentScrollView>
);
}

react-native navigation. Drawer not opening after package update

I am make using react-native. I recently had to update my react-navigation package to version 6. The issue is my drawer will no longer open and I cannot figure out how to fix it.
This is may code for my navigation:
import React from 'react';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createStackNavigator } from '#react-navigation/stack';
import { StyleSheet, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/dist/FontAwesome5';
import IonIcon from 'react-native-vector-icons/dist/Ionicons';
import { useNavigation } from '#react-navigation/native';
import { HomeScreen } from '../../screens/app/home/home.screen';
import HistoryScreen from '../../screens/app/history/history.screen';
import { SignoffScreen } from '../../screens/app/signoff/signoff.screen';
import NotificationsScreen from '../../screens/app/notifications/notifications.screen';
import useTheme from '../../theme/hooks/useTheme';
import { AppStackList, AppStackProps, DrawerList } from './types';
import { Colors } from '../../theme/Variables';
import CustomDrawerContent from '../../components/molecules/custom-drawer';
import { common } from '../../theme/Common';
import { FormScreen } from '../../screens/app/form/form.screen';
import { Menu } from '../../assets';
const AppStack = createStackNavigator<AppStackList>();
const Drawer = createDrawerNavigator<DrawerList>();
const renderIcon = (name: string, ion: boolean) => {
if (ion) {
return <IonIcon name={name} style={styles.iconStyle} />;
}
return <Icon name={name} style={styles.iconStyle} />;
};
const NotificationsNavigator = () => {
const { Gutters } = useTheme();
const navigation = useNavigation<AppStackProps>();
return (
<TouchableOpacity
style={(common.navIconStyle, Gutters.regularRMargin)}
delayPressIn={0}
onPress={navigation.navigate('Notifications', { screen: 'NotificationsScreen' })}
>
<IonIcon name="notifications-outline" style={common.navIconStyle} />
</TouchableOpacity>
);
};
const MenuNavigator = () => {
const navigation = useNavigation<AppStackProps>();
return (
<TouchableOpacity>
<Menu name="notifications-outline" style={common.navIconStyle} />
</TouchableOpacity>
);
};
const historyDrawerOptions = {
headerShown: false,
title: '',
drawerIcon: () => renderIcon('tasks', false),
headerTintColor: Colors.black,
headerRight: NotificationsNavigator,
};
const AppNavigator = () => {
const { Custom } = useTheme();
return (
<AppStack.Navigator screenOptions={Custom.globalNavigatorScreenOptions}>
<AppStack.Screen
name="App Home"
component={DrawerNavigator}
options={{ headerShown: false }}
/>
<AppStack.Screen
name="NotificationsScreen"
component={NotificationsScreen}
options={{ headerShown: false }}
/>
<AppStack.Screen name="FormScreen" component={FormScreen} options={{ headerShown: false }} />
<AppStack.Screen
name="SignoffScreen"
component={SignoffScreen}
options={{ headerShown: false }}
/>
</AppStack.Navigator>
);
};
const DrawerNavigator = () => (
<Drawer.Navigator
drawerStyle={styles.drawerStyle}
drawerContentOptions={{
activeTintColor: Colors.primary,
inactiveTintColor: Colors.white,
labelStyle: {
color: Colors.white,
},
}}
drawerContent={() => <CustomDrawerContent />}
>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
headerShown: true,
headerTitle: '',
headerTransparent: true,
headerStyle: {
height: 120,
backgroundColor: '#fff',
},
headerTitleAlign: 'center',
headerTintColor: '#002C5F',
headerRight: NotificationsNavigator,
headerRightContainerStyle: {
width: 100,
marginRight: 8,
},
headerLeft: MenuNavigator,
drawerActiveTintColor: Colors.white,
drawerInactiveTintColor: Colors.white,
drawerLabelStyle: { fontSize: 15 },
}}
/>
<Drawer.Screen name="History" component={HistoryScreen} options={historyDrawerOptions} />
</Drawer.Navigator>
);
export default AppNavigator;
The draw was working before the update but now after it wont open? My NotificationsNavigator will also not open to its screen. Can anyone help???

React Navigation 5.x nested navigation drawer not opening from menu button

When I swipe right my drawer opens, but I want it to open using a button in the header. I have place the DrawerNavigator 'createDrawer ' in side the StackNavigator'createHomeStack'.
I am getting this error:
Reference Error: Can't find variable : Navigation
I also tried this: options={({ navigation }) => ({ but then I get error:
TypeError: navigation.toggleDrawer is not a function. (In 'navigation.toggleDrawer()', 'navigation.toggleDrawer' is undefined)
Code:
import React from 'react';
import { TouchableOpacity } from 'react-native';
import {
NavigationContainer,
DrawerActions,
DefaultTheme,
DarkTheme,
useNavigation,
} from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createStackNavigator } from '#react-navigation/stack';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {
Appearance,
useColorScheme,
AppearanceProvider,
} from 'react-native-appearance';
import Feed from './src/feed';
import Detail from './src/detail';
import Screen1 from './src/screens/drawer/screen1';
import Screen2 from './src/screens/drawer/screen2';
import Screen3 from './src/screens/drawer/screen3';
import Tab1 from './src/screens/tabs/tab1';
import Tab2 from './src/screens/tabs/tab2';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
App = () => {
const colorScheme = useColorScheme();
const MyTheme = {
dark: false,
colors: {
primary: 'white',
background: 'white',
card: '#65509f',
text: 'white',
border: 'green',
},
};
createHomeStack = () => (
<Stack.Navigator>
<Stack.Screen
name='Home'
children={this.createDrawer}
options={{
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon
name='menu'
style={[{ color: 'white', marginLeft: 16 }]}
size={25}
></Icon>
</TouchableOpacity>
),
}}
/>
<Stack.Screen
name='Detail'
component={Detail}
options={{
title: 'Detail Screen',
}}
/>
<Stack.Screen name='Bottom Tabs' component={Tab1} />
<Stack.Screen name='Top Tabs' component={Tab2} />
</Stack.Navigator>
);
createDrawer = () => (
<Drawer.Navigator>
<Drawer.Screen name='Feed' component={Feed} />
<Drawer.Screen name='Contacts' component={Screen1} />
<Drawer.Screen name='Favorites' component={Screen2} />
<Drawer.Screen name='Settings' component={Screen3} />
</Drawer.Navigator>
);
return (
<AppearanceProvider>
<NavigationContainer theme={colorScheme == 'dark' ? DarkTheme : MyTheme}>
{this.createHomeStack()}
</NavigationContainer>
</AppearanceProvider>
);
};
export default App;
There are 2 approaches to handle this:
Nest the stack inside the drawer instead of drawer inside stack
Use dispatch instead of toggleDrawer:
import { DrawerActions } from '#react-navigation/native';
// ...
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
Read more about how nesting works here https://reactnavigation.org/docs/nesting-navigators#navigator-specific-methods-are-available-in-the-navigators-nested-inside
import { DrawerActions } from '#react-navigation/native';
// ...
options={({ navigation }) => ({
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity style={{ paddingLeft: 20 }}>
<Icon
name='menu'
size={25}
style={[{ color: 'black' }]}
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
</TouchableOpacity>
),
})}
You need to get navigation prop from option the dispatch drawer Action when Button is pressed. Try the below code:
options={({navigation}) => ({
title: 'Home Screen',
headerLeft: () => (
<TouchableOpacity onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
<Icon
name='menu'
style={[{ color: 'white', marginLeft: 16 }]}
size={25}
></Icon>
</TouchableOpacity>
),
})}

Header is not showing in react-navigation-drawer React-Native

I am implementing react-navigation-drawer from React Navigation Library. But facing problem related to header. The header bar is not showing in any of the screens.
This is my App.js
import React from "react";
import { StyleSheet, ScrollView, View } from "react-native";
//import DrawerNavigator from "./navigation/DrawerNavigator";
import { Platform, Dimensions } from "react-native";
import { createAppContainer } from "react-navigation";
import { createDrawerNavigator } from "react-navigation-drawer";
import Home from "./components/home";
import Contact from "./components/contact";
const WIDTH = Dimensions.get("window").width;
const RouteConfigs = {
Home: {
screen: Home
},
Contact: {
screen: Contact
}
};
const DrawerNavigatorConfig = {
drawerWidth: WIDTH * 0.75,
drawerType: "both",
initialRouteName: "Home"
};
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const MyApp = createAppContainer(DrawerNavigator);
export default class App extends React.Component {
render() {
return <MyApp />;
}
}
And this is my home screen
import React, { Component } from "react";
import { View, Image, Text, StyleSheet, ScrollView } from "react-native";
import { FontAwesomeIcon } from "#fortawesome/react-native-fontawesome";
import { faTruck, faHome } from "#fortawesome/free-solid-svg-icons";
class Home extends Component {
static navigationOptions = {
headerTitle: "Home",
drawerIcon: ({ tintColor }) => <FontAwesomeIcon size={25} icon={faHome} />
};
render() {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5F5F5",
flexDirection: "column"
},
icon: {
width: 24,
height: 24
}
});
export default Home;
Can anyone help me. Thanks in advance!!!
#hongdeveloper this is a simple example solution for react navigation 5:
function Root() {
return (
<Stack.Navigator>
<Stack.Screen options={{title: "Profile"}} name="Profile" component={Profile} />
<Stack.Screen options={{title: "Settings"}} name="Settings" component={Settings} />
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="Root" component={Root} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You can find about the navigation to a screen in a nested navigator in docs and you can try this example on Snack
The drawer navigator does not contain headers. Stack navigators must be configured to display headers.
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const Root = createStackNavigator({
Main: { screen : DrawerNavigator}
},
{
defaultNavigationOptions : ({ navigation }) => ({
title: "Screen"
})
})
const Stacks = createAppContainer(Root)
export default Stacks;
Since December 2020 you can now use the headerShown: true setting in screenOptions of your Drawer.Navigator to show the header in React Navigation 5.
See more about this issue here: https://github.com/react-navigation/react-navigation/issues/1632
See the commit and comments about the new feature in React Navigation 5 here
https://github.com/react-navigation/react-navigation/commit/dbe961ba5bb243e8da4d889c3c7dd6ed1de287c4
Late reply, But I did it with the below code.
I created separate stack navigators for each screen and after that added all the stack navigators in the drawer navigator.
The good thing is it is fully customized.
Please see my code below.
const WIDTH = Dimensions.get('window').width;
const HomeNavigator = createStackNavigator(
{
Home: Home
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerStyle: {
backgroundColor: '#1e89f4'
},
headerTitle: 'Knowledge Woledge',
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
flex: 1
},
headerLeft: (
<View style={{ paddingLeft: 13 }}>
<FontAwesomeIcon
size={25}
color='#fff'
icon={faBars}
onPress={() => navigation.openDrawer()}
/>
</View>
),
headerRight: <View />
};
}
}
);
const DetailNavigator = createStackNavigator(
{
PostDetail: PostDetail
},
{
defaultNavigationOptions: ({ navigation }) => {
return {
headerStyle: {
backgroundColor: '#1e89f4'
},
headerTitle: () => {
return (
<Text
style={{
color: '#fff',
fontWeight: 'bold',
textAlign: 'center',
flex: 1,
fontSize: 20
}}
>
{navigation.getParam('headerTitle')}
</Text>
);
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
textAlign: 'center',
flex: 1
},
headerLeft: (
<View style={{ paddingLeft: 13 }}>
<FontAwesomeIcon
size={25}
color='#fff'
icon={faArrowLeft}
onPress={() => navigation.goBack(null)}
/>
</View>
),
headerRight: <View />
};
}
}
);
Assigned this in a const
const RouteConfigs = {
Home: {
screen: HomeNavigator,
navigationOptions: {
drawerLabel: 'Home',
drawerIcon: ({ tintColor }) => (
<FontAwesomeIcon size={20} color={tintColor} icon={faHome} />
)
}
},
Detail: {
screen: DetailNavigator,
navigationOptions: {
drawerLabel: () => {
return null;
}
}
}
};
And finally, create a drawer navigator with this.
const DrawerNavigatorConfig = {
drawerWidth: WIDTH * 0.75,
drawerType: 'both',
initialRouteName: 'Home'
};
const DrawerNavigator = createDrawerNavigator(
RouteConfigs,
DrawerNavigatorConfig
);
const Stacks = createAppContainer(DrawerNavigator);
export default Stacks;

Add custom icon to drawer navigation

I am trying to add custom icon to my CustomDrawerComponent, but nothing happen...
App.js :
const navigationOptions = {
headerTintColor: colors.white,
};
const drawerNavigationOption = ({ navigation }) => ({
...navigationOptions,
headerLeft: (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<View>
<Icon name="menu" size={24} color={colors.white} />
</View>
</TouchableOpacity>
),
});
const MapsStackNavigator = createStackNavigator({
MapsNavigator: {
screen: MapsScreen,
navigationOptions: drawerNavigationOption,
},
});
const AppDrawerNavigator = createDrawerNavigator(
{
Plans: MapsStackNavigator,
},
{
contentComponent: CustomDrawerMenu,
contentOptions: {
inactiveTintColor: colors.doveGrey,
activeTintColor: colors.doveGrey,
},
}
);
My CustomDrawerMenu.js :
export default class CustomDrawerMenu extends Component {
render() {
return (
<ScrollView
contentContainerStyle={{
flex: 1,
flexDirection: "column",
justifyContent: "space-between",
}}
>
<SafeAreaView forceInset={{ top: "always", horizontal: "never" }}>
{...}
<DrawerItems {...this.props} />
</SafeAreaView>
{...}
</ScrollView>
);
}
}
My MapsScreen :
export default class MapsScreen extends React.Component {
static navigationOptions = {
drawerIcon: (
<Image
style={{ width: 24, height: 24 }}
source={require("../../assets/icons/plan.png")}
/>
),
title: "Plans",
};
render() {
return (
<Text>My map screen</Text>
);
}
}
But absolutely nothing happened... I tried to add drawerIcon to my App.js > const navigationOptions but nothing happened aswell.
I do not really know where to place drawerIconm because I search on the doc, on some YouTubes video and when I reproduced the same, it does not work.
Thank you.
In the new version of react-navigation(5.x)
You have to do :
1-
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
import Icon from 'react-native-vector-icons/Ionicons';
2- Instead of using createDrawerNavigator you have to use Drawer.Navigator as below :
<NavigationContainer>
<Drawer.Navigator
initialRouteName="Products">
<Drawer.Screen name="Products" component={YOUR COMPONENT OR YOUR STACKNAVIGATOR} options={{
drawerIcon: config => <Icon
size={23}
name={Platform.OS === 'android' ? 'md-list' : 'ios-list'}></Icon>
}} />
<Drawer.Screen name="Orders" component={YOUR COMPONENT OR YOUR STACKNAVIGATOR} options={{
drawerIcon: config => <Icon
size={23}
name={Platform.OS === 'android' ? 'md-create' : 'ios-create'}></Icon>
}} />
</Drawer.Navigator>
</NavigationContainer>
I finally found the answer myself, you can not add drawerIcon to navigationOptions of the child-screen. You have to do like so :
const AppDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: HomeStackNavigator,
navigationOptions: {
drawerIcon: (
<Image
style={{ width: 24, height: 24 }}
source={require("./assets/icons/plan.png")}
/>
),
},
},
And then in your HomeStack :
const HomeStackNavigator = createStackNavigator({
HomeNavigator: {
screen: HomeScreen,
navigationOptions: drawerNavigationOption,
},
});
Hope it'll serve to someone !
<Stack.Screen name="Feed" component={Feed} options={{ title: 'Feed',
drawerIcon: ({ focused, size }) => (
<Image
source={require('../../../assets/icons/icon-email.png')}
style={[{ height: 20, width: 20 }]}
/> )
}} />
const AppDrawerNavigator = createDrawerNavigator(
{
Home: {
screen: HomeStackNavigator,
navigationOptions: {
drawerIcon: (
<View>
<Image
style={{ width: 24, height: 24 }}
source={require("./assets/icons/plan.png")}
/>
</View>
),
},
},
Add before you will get original image style
hope this will save someone days..
import { NavigationContainer } from "#react-navigation/native";
<NavigationContainer>
<Drawer /> //import from your folder/file
</NavigationContainer>
drawer file
import { createDrawerNavigator } from "#react-navigation/drawer";
import DrawerContain from "./DrawerContain";
import StackNavigatore from "./stackNavigatore";
import ProductHome from "../product/ProductHome";
import Contact from "./ContactUs";
import About from "./About";
import HomeOrder from "./orderStack";
function DrawerNavigator() {
return (
<Drawer.Navigator
drawerContent={(props) => <DrawerContain {...props} />}
drawerContentOptions={
{
// activeTintColor: "#e91e63",
// itemStyle: { marginVertical: 5 },
}
}
>
<Drawer.Screen name="Home" component={StackNavigatore} />
<Drawer.Screen
name="Order"
component={HomeOrder}
/>
<Drawer.Screen name="Contact Us" component={Contact} />
<Drawer.Screen name="About Us" component={About} show={false} />
</Drawer.Navigator>
);
}
export default DrawerNavigator;
drawer container file
import {
DrawerContentScrollView,
DrawerItemList,
DrawerItem,
} from "#react-navigation/drawer";
import { View, StyleSheet } from "react-native";
import { useNavigation } from "#react-navigation/native";
import React from "react";
import Ionicons from "react-native-vector-icons/Ionicons";
import { Drawer, Text } from "react-native-paper";
function DrawerContain({ ...props }) {
// const navigation = useNavigation();
const image = require("../../assets/img/rupee.png");
return (
<>
<Drawer.Section>
<DrawerItem
icon={({ color, size }) => (
<Ionicons name="home-outline" color={color} size={size} /> <<--- with
vectore icon
)}
label="Sell prodcuts to customer"
// onPress={() => props.navigation.navigate('route to screen')}
/>
<Drawer.Item
icon={image} <<---- from local storage
label="Orders"
onPress={() => props.navigation.navigate("Order")}
/>
</>
)
}