React Native course ยท Module 3: Navigation
Drawer Navigation - Palace Side Menu
In this lesson7
Drawer Navigation is a slide-out side menu, perfect for applications with many sections or settings.
Installation
npx expo install @react-navigation/drawer
npx expo install react-native-gesture-handler react-native-reanimatedConfiguring babel.config.js
// babel.config.js
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'], // Must be last!
};
};Basic Drawer
import { createDrawerNavigator } from '@react-navigation/drawer';
import { Ionicons } from '@expo/vector-icons';
type DrawerParamList = {
Home: undefined;
Profile: undefined;
Settings: undefined;
Help: undefined;
};
const Drawer = createDrawerNavigator<DrawerParamList>();
function App() {
return (
<NavigationContainer>
<Drawer.Navigator
screenOptions={{
drawerStyle: {
backgroundColor: '#0a2e4a',
width: 280,
},
drawerActiveTintColor: '#00d4ff',
drawerInactiveTintColor: '#a0aec0',
drawerLabelStyle: {
marginLeft: -20,
fontSize: 16,
},
headerStyle: {
backgroundColor: '#0a2e4a',
},
headerTintColor: '#fff',
}}
>
<Drawer.Screen
name="Home"
component={HomeScreen}
options={{
drawerIcon: ({ color, size }) => (
<Ionicons name="home" size={size} color={color} />
),
drawerLabel: 'Home page',
}}
/>
<Drawer.Screen
name="Profile"
component={ProfileScreen}
options={{
drawerIcon: ({ color, size }) => (
<Ionicons name="person" size={size} color={color} />
),
}}
/>
<Drawer.Screen
name="Settings"
component={SettingsScreen}
options={{
drawerIcon: ({ color, size }) => (
<Ionicons name="settings" size={size} color={color} />
),
}}
/>
</Drawer.Navigator>
</NavigationContainer>
);
}Custom Drawer Content
import {
DrawerContentScrollView,
DrawerItemList,
DrawerItem
} from '@react-navigation/drawer';
function CustomDrawerContent(props: DrawerContentComponentProps) {
const { navigation } = props;
return (
<DrawerContentScrollView {...props}>
{/* Header with user profile */}
<View style={styles.drawerHeader}>
<Image
source={{ uri: 'https://example.com/avatar.jpg' }}
style={styles.avatar}
/>
<Text style={styles.username}>Poseidon</Text>
<Text style={styles.email}>poseidon@atlantis.sea</Text>
</View>
{/* Separator */}
<View style={styles.separator} />
{/* Default screen list */}
<DrawerItemList {...props} />
{/* Separator */}
<View style={styles.separator} />
{/* Additional items */}
<DrawerItem
label="Help"
icon={({ color, size }) => (
<Ionicons name="help-circle" size={size} color={color} />
)}
onPress={() => {
// Custom action
alert('Atlantis Help Center');
}}
/>
<DrawerItem
label="Log out"
icon={({ color, size }) => (
<Ionicons name="log-out" size={size} color={color} />
)}
onPress={() => {
// Logout logic
navigation.closeDrawer();
}}
/>
</DrawerContentScrollView>
);
}
// Usage
<Drawer.Navigator
drawerContent={(props) => <CustomDrawerContent {...props} />}
>
{/* Screens */}
</Drawer.Navigator>Opening/Closing Drawer Programmatically
import { useNavigation, DrawerActions } from '@react-navigation/native';
function HomeScreen() {
const navigation = useNavigation();
return (
<View>
<Pressable onPress={() => navigation.dispatch(DrawerActions.openDrawer())}>
<Text>Open menu</Text>
</Pressable>
<Pressable onPress={() => navigation.dispatch(DrawerActions.closeDrawer())}>
<Text>Close menu</Text>
</Pressable>
<Pressable onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}>
<Text>Toggle menu</Text>
</Pressable>
</View>
);
}Drawer on the Right Side
<Drawer.Navigator
screenOptions={{
drawerPosition: 'right', // Default is 'left'
}}
>
{/* Screens */}
</Drawer.Navigator>Nesting Navigators
function MainStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="MainTabs"
component={MainTabs}
options={{ headerShown: false }}
/>
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
);
}
function App() {
return (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen
name="Main"
component={MainStack}
options={{ headerShown: false }}
/>
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}Drawer Navigation works great in applications with many sections, admin panels, and enterprise applications.
Code for this lesson: App.tsx
import React from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import {
DrawerContentScrollView,
DrawerItemList,
} from '@react-navigation/drawer';
// Custom Drawer content with a profile header
function CustomDrawerContent(props) {
return (
<DrawerContentScrollView {...props}>
{/* TODO: add a profile header inside <View style={styles.header}>:
- <Image style={styles.avatar} source={{ uri: 'https://i.pravatar.cc/100' }} />
- <Text style={styles.name}>Poseidon</Text> */}
{/* TODO: below the header render the default item list: <DrawerItemList {...props} /> */}
</DrawerContentScrollView>
);
}
const styles = StyleSheet.create({
header: {
padding: 20,
alignItems: 'center',
backgroundColor: '#1a5276',
marginBottom: 8,
},
avatar: {
width: 72,
height: 72,
borderRadius: 36,
marginBottom: 10,
},
name: {
color: '#fff',
fontSize: 18,
fontWeight: '600',
},
});
export default CustomDrawerContent;Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. Which libraries are required for Drawer Navigator?
2. How do you set the Drawer on the right side of the screen?
Hands-on tasks in the game
- Click in order
Click the elements to open a Drawer programmatically:
- Code editor
Complete the CustomDrawerContent code.