Expo Router Drawer Navigation - From the Docs
Overview
Welcome to the third installment of my Expo Router file-based routing video series! In this series, I will be diving into various aspects of Expo Router, including basic routing, dynamic routes, and the Drawer Navigator.
As I delved into working with the new router, I initially started with the basic two-tab template, which has been a valuable starting point. However, there were instances where I found myself puzzled by the magic happening behind the scenes.
To address this, I decided to take a step back and create these videos from scratch. Together, we will add Expo Router to a basic Expo application and follow the documentation closely as we build the Drawer Navigation based application. Along the way, I'll be sharing all the steps I take in detail, as I felt the existing documentation on using the Drawer Navigator from scratch wasn't very clear, in my honest opinion.
I'm excited about this journey, and I hope you'll join me as we explore Expo Router and its functionalities. Feel free to share this content with your friends and associates as well—let's learn and grow together!
The Steps
Run this command to build the app project
npx create-expo-app@latest --template blank@sdk-49 drawer-expo-router
Change into the project directory and install the additional dependencies
npx expo install expo-router@latest react-native-safe-area-context react-native-screens expo-linking expo-constants expo-status-bar react-native-gesture-handler
Add addition dependencies that are needed for the Drawer Navigator
npx expo install @react-navigation/drawer react-native-gesture-handler react-native-reanimated
Open the package.json
file and make the following update
{
"main": "expo-router/entry"
}
Not using web so skipping that part of documentation, but add the scheme app.json
"scheme": "myappdrawersexporouter",
update babel.config.js
to include the new plugin for expo-router
and an additional one is needed for react-native-reanimated
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin','expo-router/babel'],
};
};
Lets add the index page and then test it is working, remember the files all live in a new app directory that you have to create. /app/index.js
import { Redirect } from 'expo-router';
import { Text } from 'react-native';
export default function Page() {
return <Text>INDEX PAGE</Text>;
}
At this point you should be able to run the application and see the index page to confirm the basic installation and configuration of the application is completed
Adding The Drawer
Lets add a group for drawer by creating a folder with the folder name "drawer" in parenthesis, /app/(drawer)
(drawer)
then add a new _layout.js
file in the "(drawer)" folder. The directory should look like this /app/(drawer)/_layout.js
. We are adding the Drawer UI component and adding one Drawer menu item called "Home".
import { Drawer } from "expo-router";
export default function DrawerLayout() {
return (
<Drawer
screenOptions={{ headerShown: false}}
>
<Drawer.Screen
name="home"
options={{
drawerLabel: "Home",
title: "Home",
}}
/>
</Drawer>
);
}
We are creating the Drawer
navigation component with this code and then creating the UI with the following lines of code. This code will create the Drawer with one menu item and associated route home
; we will create that route next.
<Drawer
screenOptions={{ headerShown: false }}
>
<Drawer.Screen
name="home"
options={{
drawerLabel: "Home",
title: "Home",
}}
/>
</Drawer>
Create a new folder name "home" and add a file named index.js
to that folder. The new file will be the index page of the Home Drawer Item stack. The directory should look like this /app/(drawer)/home/index.js
import { Text, View, StyleSheet } from "react-native";
export default function Page() {
return (
<>
<View style={styles.container}>
<Text style={{ fontSize: 24 }}>Index page of Home Drawer</Text>
</View>
</>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
But we need a layout for the home folder, so add a new file with the contents below. /app/(drawer)/home/_layout.js
import { Stack } from "expo-router";
export default function HomeLayout() {
return <Stack />;
}
Now we need to update the /app/index.js
to redirect to the /app/(drawer)/home
at start up.
import { Redirect } from 'expo-router';
import { Text } from 'react-native';
export default function Page() {
return <Redirect href={"/(drawer)/home"} />;
}
At this point you should be able to run the app and swipe from the left to see the new Drawer with one menu item. Let make some modifications so the Drawer performs as expected.
We are going to add the Drawer menu button adn make it so the Drawer cannot be swiped open. First the menu button.
Open the /app/(drawer)/home/index.js
file and add a new import
import { DrawerToggleButton } from "@react-navigation/drawer";
then modify the Drawer.Screen
options to include the headerLeft
property to show the DrawerToggleButton
<Drawer.Screen
options={{
title: "Home",
headerShown: true,
headerLeft: () => <DrawerToggleButton />
}}
/>
Next to make sure the user cannot swipe the Drawer open, we can modify the options of the Drawer
component in the /app/(drawer)/_layout.js
file; Set the swipeEdgeWidth
to 0.
<Drawer
screenOptions={{ headerShown: false, swipeEdgeWidth : 0}}
>
Now lets add a second Drawer
menu item. To make things easier, just copy the home folder and rename the new copy to settings, then edit the index.js
file in the settings folder with the following code.
import { Text, StyleSheet, View } from "react-native";
import { Drawer } from "../_layout";
import { DrawerToggleButton } from "@react-navigation/drawer";
export default function Page() {
return (
<View style={styles.container}>
<Drawer.Screen
options={{
title: "Settings", // <== NEW EDIT HERE
headerShown: true,
headerLeft: () => <DrawerToggleButton />,
}}
/>
<Text style={{ fontSize: 24 }}> // <== NEW EDIT HERE
Index page of Settings Drawer
</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
I also suggest editing the /app/(drawer)/settings/_layout.js
file; just editing the name of the component to SettingsLayout
import { Stack } from "expo-router";
export default function SettingsLayout() {
return <Stack />;
}
Finally lets add the new Drawer.Screen
in /app/(drawer)/_layout.js
export default function DrawerLayout() {
return (
<Drawer
screenOptions={{ headerShown: false, swipeEdgeWidth : 0}}
>
<Drawer.Screen
name="home"
options={{
drawerLabel: "Home",
title: "Home",
}}
/>
{/* /// new code below /// */}
<Drawer.Screen
name="settings"
options={{
drawerLabel: "Settings",
title: "Settings",
}}
/>
</Drawer>
);
}
Nested Navigation With Home
Create a new page next-page.js
in the Home folder; /app/(drawer)/home/next-page.js
and add the following code.
import { Stack } from "expo-router";
import { Text, View, StyleSheet } from "react-native";
export default function NextPage() {
return (
<View style={styles.container}>
<Stack.Screen options={{ headerShown: true, title: "Next Page" }} />
<Text style={{ fontSize: 24 }}>Next page of Home Tab</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
To get to that page, we will add a new button to the file /app/(drawer)/home/index.js
.
first import Link
import { Link } from "expo-router";
the add the new link to the content section of the page
<Link href={"/home/next-page"} style={{ marginTop: 16, fontSize: 18 }}>
<Text style={{ fontWeight: "bold" }}>Go To Next Page</Text>
</Link>
now you should be able to navigate to next-page
and have the back button appear in the header to navigate back. In this instance, I am not including the DrawerButton
on the next-page
so you would need to navigate back to change the menu item.
Wrap
Well, I hope you found this helpful, I think it is a bit more detailed than what the documentation provided and it can also be beneficial to those looking for something without typescript.
Links
Expo Router Doc - https://docs.expo.dev/routing/installation/#manual-installation
Expo Router Drawer Doc - https://docs.expo.dev/router/advanced/drawer/
React Navigation Drawer Documentation - https://reactnavigation.org/docs/drawer-navigator/
Stack Navigation Video - https://youtu.be/wBjy08dxL8I
Social Media
YouTube - https://www.youtube.com/@AaronSaundersCI
Twitter - https://twitter.com/aaronksaunders
Instagram - https://www.instagram.com/aaronksaunders/
Dev.to - https://dev.to/aaronksaunders
Subscribe to my newsletter
Read articles from Aaron K Saunders directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Aaron K Saunders
Aaron K Saunders
🎓 Udemy Courses - https://www.udemy.com/user/aaronsaunders/ 🎓 Gumroad Courses/Content - https://www.gumroad.com/fiwic