Creating a Drawer Navigation in a React Native App with React Navigation and Redux
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