Expo Router Drawer Navigation - From the Docs
Tags: react, reactnative, expo, tutorial
Published: 2023-07-26 16:20:54

### Overview
Welcome to the third installment of my [Expo Router file-based routing video series](https://www.youtube.com/playlist?list=PL2PY2-9rsgl2DikpQG-GgO7TBgRtdB6NT)! In this series, I will be diving into various aspects of [Expo Router](https://docs.expo.dev/routing/installation/#manual-installation), including basic routing, dynamic routes, and the [Drawer Navigator](https://docs.expo.dev/router/advanced/drawer/).

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.

{% youtube DOYl5PdFC6U %}

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
```jsx
npx create-expo-app@latest --template blank@sdk-49  drawer-expo-router
```

Change into the project directory and install the additional dependencies

```jsx
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
```jsx
npx expo install @react-navigation/drawer react-native-gesture-handler react-native-reanimated
```

Open the `package.json` file and make the following update

```jsx
{
  "main": "expo-router/entry"
}
```

Not using web so skipping that part of documentation, but add the scheme `app.json`

```jsx
"scheme": "myappdrawersexporouter",
```

update `babel.config.js` to include the new plugin for `expo-router` and an additional one is needed for `react-native-reanimated`

```jsx
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`
```jsx
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)`

```jsx
(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".

```jsx
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.
```jsx
    <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`
```jsx
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`
```jsx
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.
```jsx
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
```javascript
import { DrawerToggleButton } from "@react-navigation/drawer";
```

then modify the `Drawer.Screen` options to include  the `headerLeft` property to show the `DrawerToggleButton`
```jsx
    <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.
```jsx
<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.
```jsx
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`
```jsx
import { Stack } from "expo-router";

export default function SettingsLayout() {
  return <Stack />;
}
```

Finally lets add the new `Drawer.Screen` in `/app/(drawer)/_layout.js`
```jsx
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.
```jsx
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`
```jsx
import { Link } from "expo-router";
```

the add the new link to the content section of the page
```jsx
  <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 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
Facebook - https://www.facebook.com/ClearlyInnovativeInc
Instagram - https://www.instagram.com/aaronksaunders/
Dev.to - https://dev.to/aaronksaunders