Search

Suggested keywords:
  • Java
  • Docker
  • Git
  • React
  • NextJs
  • Spring boot
  • Laravel

React Native Navigation and Routing with Expo: A Comprehensive Guide

  • Share this:

post-title

Navigation is a cornerstone of mobile app development, providing users with a seamless and intuitive way to explore and interact with different sections of an application. In the React Native ecosystem, React Navigation stands out as a powerful and flexible library for managing navigation and routing.

In this extensive guide, we will delve into various navigation techniques using React Navigation within the Expo framework. To make things more engaging, we'll build a comprehensive example app covering stack navigation, tab navigation, and even a custom navigator.

To get basics about React Native, refer to our previous posts.

Setting Up the Project with Expo

Before we dive into the intricacies of navigation, let's set up a new Expo project. Ensure you have Expo CLI installed:

npm install -g expo-cli

 

Now, create a new Expo project:

expo init NavigationExample
cd NavigationExample

 

Choose the "blank" template for simplicity. Once the project is created, navigate to its directory and install the necessary dependencies:

cd NavigationExample


npm install @react-navigation/native @react-navigation/stack @react-navigation/bottom-tabs react-native-paper react-native-vector-icons

These additional packages, `react-native-paper` for styling and `react-native-vector-icons` for icons, will enhance the visual appeal of our example app.

Stack Navigation

App.js

Let's begin by setting up a simple stack navigator. Stack navigation is a common pattern where screens are organized in a stack, allowing users to navigate forward and backward through the stack.

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Stack = createStackNavigator();

export default function App() {
 return (
   <NavigationContainer>
     <Stack.Navigator initialRouteName="Home">
       <Stack.Screen name="Home" component={HomeScreen} />
       <Stack.Screen name="Details" component={DetailsScreen} />
     </Stack.Navigator>
   </NavigationContainer>
 );
}

Explanation:

- `NavigationContainer`: The root component that manages the navigation tree.

- `createStackNavigator`: Creates a stack navigator.

- `Stack.Navigator`: The stack navigator component, where screens are defined.

- `Stack.Screen`: Defines individual screens within the stack.

 

HomeScreen.js

Now, let's create a basic Home screen component:

import React from 'react';
import { View, Text, Button } from 'react-native';

export default function HomeScreen({ navigation }) {
 return (
   <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
     <Text style={{ fontSize: 24 }}>Welcome to the Home Screen!</Text>
     <Button
       title="Go to Details"
       onPress={() => navigation.navigate('Details')}
       style={{ marginTop: 20 }}
     />
   </View>
 );
}

 

DetailsScreen.js

And a corresponding Details screen:

import React from 'react';
import { View, Text } from 'react-native';

export default function DetailsScreen() {
 return (
   <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
     <Text style={{ fontSize: 24 }}>Details Screen</Text>
   </View>
 );
}

 

screenshot

 

screenshot

With these simple components, we've set up basic stack navigation.

Tab Navigation

Now, let's enhance our app by adding tab navigation. Tab navigation is an effective way to organize an app into different sections.

 

App.js (updated)

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';

import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Tab = createBottomTabNavigator();

export default function App() {
 return (
   <NavigationContainer>
     <Tab.Navigator
       initialRouteName="Home"
       tabBarOptions={{
         activeTintColor: '#3498db',
         inactiveTintColor: 'gray',
       }}
     >
       <Tab.Screen
         name="Home"
         component={HomeScreen}
         options={{
           tabBarLabel: 'Home',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="home"
               color={color}
               size={size}
             />
           ),
         }}
       />
       <Tab.Screen
         name="Details"
         component={DetailsScreen}
         options={{
           tabBarLabel: 'Details',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="information"
               color={color}
               size={size}
             />
           ),
         }}
       />
     </Tab.Navigator>
   </NavigationContainer>
 );
}

 

Explanation:

- `createBottomTabNavigator`: Creates a tab navigator.

- `Tab.Navigator`: The tab navigator component.

- `Tab.Screen`: Defines individual screens within the tab navigator.

- `MaterialCommunityIcons`: Icon component from `react-native-vector-icons` for a material design icon set.

This update adds tab navigation with icons to our app.

 

screenshot

screenshot

 

Custom Navigator

Sometimes, the default navigators may not fully meet our app's needs. In such cases, React Navigation allows us to create custom navigators. Let's create a custom navigator to demonstrate this.

 

CustomStackNavigator.js

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';

import CustomScreen from './screens/CustomScreen';

const Stack = createStackNavigator();

export default function CustomStackNavigator() {
 return (
   <Stack.Navigator>
     <Stack.Screen
       name="Custom"
       component={CustomScreen}
       options={{
         title: 'Custom Screen',
         headerStyle: {
           backgroundColor: '#3498db',
         },
         headerTintColor: '#fff',
         headerTitleStyle: {
           fontWeight: 'bold',
         },
       }}
     />
   </Stack.Navigator>
 );
}

 

App.js (updated)

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';

import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
import CustomStackNavigator from './CustomStackNavigator';

const Tab = createBottomTabNavigator();

export default function App() {
 return (
   <NavigationContainer>
     <Tab.Navigator
       initialRouteName="Home"
       tabBarOptions={{
         activeTintColor: '#3498db',
         inactiveTintColor: 'gray',
       }}
     >
       <Tab.Screen
         name="Home"
         component={HomeScreen}
         options={{
           tabBarLabel: 'Home',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="home"
               color={color}
               size={size}
             />
           ),
         }}
       />
       <Tab.Screen
         name="Details"
         component={DetailsScreen}
         options={{
           tabBarLabel: 'Details',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="information"
               color={color}
               size={size}
             />
           ),
         }}
       />
       <Tab.Screen
         name="Custom"
         component={CustomStackNavigator}
         options={{
           tabBarLabel: 'Custom',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="puzzle"
               color={color}
               size={size}
             />
           ),
         }}
       />
     </Tab.Navigator>
   </NavigationContainer>
 );
}

 

Explanation:

- `createStackNavigator`: Creates a stack navigator.

- `Stack.Navigator`: The stack navigator component for our custom screen.

- `Stack.Screen`: Defines individual screens within the stack.

- Options in `CustomStackNavigator`: Customization of the navigation header.

With this setup, we've integrated a custom navigator into our app, showcasing the flexibility of React Navigation.

 

Styling and Icons

Let's enhance the visual appeal of our app with some styling and icons.

 

styles.js

Create a file named `styles.js` in the project root:

import { StyleSheet } from 'react-native';

export const globalStyles = StyleSheet.create({
 container: {
   flex: 1,
   justifyContent: 'center',
   alignItems: 'center',
   backgroundColor: '#ecf0f1',
 },
 titleText: {
   fontSize: 24,
   fontWeight: 'bold',
   marginBottom: 20,
 },
 button: {
   marginTop: 20,
 },
});

export const tabStyles = StyleSheet.create({
 tabBarIcon: {
   marginBottom: -3,
 },
});

 

Explanation:

- `globalStyles`: Contains styling for the overall app layout.

- `tabStyles`: Contains styling for tab bar icons to adjust their positioning.

 

App.js (updated)

import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialCommunityIcons } from '@expo/vector-icons';

import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';
import CustomStackNavigator from './CustomStackNavigator';
import { globalStyles, tabStyles } from './styles';

const Tab = createBottomTabNavigator();

export default function App() {
 return (
   <NavigationContainer>
     <Tab.Navigator
       initialRouteName="Home"
       tabBarOptions={{
         activeTintColor: '#3498db',
         inactiveTintColor: 'gray',
         labelStyle: {
           fontSize: 12,
           marginBottom: 5,
         },
         style: {
           backgroundColor: '#ecf0f1',
         },
       }}
     >
       <Tab.Screen
         name="Home"
         component={HomeScreen}
         options={{
           tabBarLabel: 'Home',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="home"
               color={color}
               size={size}
             />
           ),
         }}
       />
       <Tab.Screen
         name="Details"
         component={DetailsScreen}
         options={{
           tabBarLabel: 'Details',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="information"
               color={color}
               size={size}
             />
           ),
         }}
       />
       <Tab.Screen
         name="Custom"
         component={CustomStackNavigator}
         options={{
           tabBarLabel: 'Custom',
           tabBarIcon: ({ color, size }) => (
             <MaterialCommunityIcons
               name="puzzle"
               color={color}
               size={size}
             />
           ),
         }}
       />
     </Tab.Navigator>
   </NavigationContainer>
 );
}

 

screenshot

screenshot

Now, our app has a consistent style, and the tab bar icons are properly positioned.

 

Conclusion

In this comprehensive guide, we've explored various navigation techniques in React Native using React Navigation within the Expo framework. From stack navigation to tab navigation and custom navigators, we've covered it all. The example app we've built incorporates styling and icons for a polished look.

Feel free to adapt this code for your projects and explore the official React Navigation documentation for more advanced features and customization options.

Happy coding!

Utkarsh Krishna

About author
Hey there! I'm Utkarsh Krishna, an Open Source, Full-Stack Web Development, Java Development, and Developer Blogging enthusiast. Currently, I'm learning Full-Stack Web Development and Java, and I'm excited to share my journey and learnings through my blogs. Join me on this exciting adventure as we explore the world of software development together!