Creating a Drawer Navigation in a React Native App with React Navigation and Redux

Tywo Taiwo
3 min readFeb 8, 2024

--

In this tutorial, we’ll go through setting up a drawer navigation in a React Native app using React Navigation and Redux. This setup includes integrating authentication state management with Redux, allowing for dynamic navigation based on the user’s authentication status. This guide assumes you have a React Native project set up and are familiar with Redux for state management.

Step 1: Install Dependencies

First, ensure you have React Navigation and its dependencies installed in your project:

bashCopy codenpm install @react-navigation/native @react-navigation/drawer
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context

For iOS, don’t forget to run pod install in your iOS directory to link the native code. For Android, ensure you've followed the additional setup required for react-native-gesture-handler in your MainActivity.java.

Step 2: Import Gesture Handler

To ensure gesture handling works properly, especially for Android, import react-native-gesture-handler at the very top of your index.js or your entry file:

import 'react-native-gesture-handler';
import React from 'react';
import { AppRegistry } from 'react-native';
import App from './App'; // Adjust the path as necessary
import { name as appName } from './app.json';

Step 3: Define Your Navigation Structure

In your app, define the navigators. We’ll use a stack navigator for authentication screens and a drawer navigator for the main app interface. Let’s start by setting up the stack navigators for authentication:

// src/navigation/AuthNavigation.js
import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import LoginScreen from '../screens/LoginScreen';
import SignupScreen from '../screens/SignupScreen';
const Stack = createStackNavigator();const AuthNavigation = () => (
<Stack.Navigator>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Signup" component={SignupScreen} />
</Stack.Navigator>
);
export default AuthNavigation;

Next, define your drawer navigator for the main app interface. This example includes a logout button directly in the drawer for simplicity:

// src/navigation/AppNavigation.js
import React from 'react';
import { createDrawerNavigator } from '@react-navigation/drawer';
import HomeScreen from '../screens/HomeScreen';
import SettingsScreen from '../screens/SettingsScreen';
import LogoutButton from '../components/LogoutButton';
const Drawer = createDrawerNavigator();const AppNavigation = () => (
<Drawer.Navigator initialRouteName="Home" drawerContent={(props) => <LogoutButton {...props} />}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Settings" component={SettingsScreen} />
</Drawer.Navigator>
);

Step 4: Integrate Redux for Authentication State Management

To manage the authentication state, use Redux. Dispatch actions based on authentication events (login, logout) and reflect these changes in your navigational structure. Here’s a simplified setup:

// src/redux/store.js
import { configureStore } from '@reduxjs/toolkit';
import authReducer from './slices/authSlice';
export const store = configureStore({
reducer: {
auth: authReducer,
},
});

Your authSlice would manage the authentication state, including the current user's ID and authentication status.

Step 5: Combine Navigation and Redux

In your main App component, use the Redux store and select which navigation stack to display based on the user’s authentication status:

// App.js
import React, { useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { Provider, useSelector, useDispatch } from 'react-redux';
import { store } from './redux/store';
import AuthNavigation from './navigation/AuthNavigation';
import AppNavigation from './navigation/AppNavigation';
import { checkAuthStatus } from './redux/slices/authSlice'; // An example action to check auth status
const RootNavigation = () => {
const authStatus = useSelector((state) => state.auth.status);
const dispatch = useDispatch();
useEffect(() => {
dispatch(checkAuthStatus());
}, [dispatch]);
return (
<NavigationContainer>
{authStatus === 'authenticated' ? <AppNavigation /> : <AuthNavigation />}
</NavigationContainer>
);
};
const App = () => (
<Provider store={store}>
<RootNavigation />
</Provider>
);
export default App;

Step 6: Update Your Babel Configuration

Open or create a babel.config.js file at the root of your React Native project and include the react-native-reanimated/plugin like so:

module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
'react-native-reanimated/plugin',
],
};

This plugin is necessary for the reanimated library to work with the new React Native architecture and to enable advanced animation features.

Step 7: Restart Your Metro Bundler

After updating your Babel configuration, you need to restart your Metro bundler to ensure the changes take effect. Close any running Metro bundler terminals and rebuild your project:

  • For iOS, run npx react-native run-ios in your terminal.
  • For Android, run npx react-native run-android.

This step ensures that your Babel configuration is reloaded and that react-native-reanimated works as expected within your app.

Step 8: Testing Your Setup

Run your app on iOS or Android. You should be able to navigate between your login/signup screens and the main app. The drawer should open with a gesture or by tapping the menu button, showing the logout option and other navigation items you’ve set up

--

--