ReactNav: Building a Dynamic Base Navigator with React Native for Seamless Exploration

ReactNav: Building a Dynamic Base Navigator with React Native for Seamless Exploration

Step 1: Create a new Expo project

Navigate to the directory where you want to create your new app and run the following command:

npx create-expo-app@latest

Step 2: Run the Expo development server

Navigate into the newly created project directory:

cd my-app

Start the development server by running:

npm expo start

This will launch the Expo development server, and you'll see a QR code in the terminal.

Step 3: Install the required packages in your React Native project

npm install @react-navigation/native
npm i @react-navigation/stack

Step 4: Create Screens that will be displayed within the app Base Navigator

a. Create the necessary components:

  • Inside your React Native project, create separate TypeScript files for each component that you want to display in the base navigator. For example, you can create HomeScreen.tsx, SearchScreen.tsx, PostScreen.tsx, MapScreen.tsx, ProfileScreen.tsx file.

b. Define the content for each component:

  • In each component file, define the content that you want to display when the corresponding item is selected in the base navigator. This content can include UI elements, such as text, images, buttons, or any other desired components.

Try this example: HomeScreen.tsx

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

const HomeScreen: React.FC = () => {
  return (
    <View style={styles.container}>
      <Text>Home</Text>
    </View>
  );
};

export default HomeScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
});

Step 5: Create "BottomTabs" folder in your project

Step 6: Create Base Navigator for your application

* Out of the three diverse Base Navigators available, feel free to select the one that suits your preference and integrate it into your project.

Install the React-Native Vector Icons package, enabling you to incorporate diverse and visually appealing icons into your React Native Application.

npm i react-native-vector-icons

* First: Material Bottom Navigator

step A: Install @react-navigation/material-bottom-tabs package

npm i @react-navigation/material-bottom-tabs

step B: Create "MaterialBottomTab.tsx" file in "BottomTabs" folder

  • Import "CreateMaterialBottomTabNavigator" from @react-navigation/material-bottom-tabs

  • Import IonIcons from react-native-vector-icons/Ionicons

  • Import the specific screens that you want to display

Try this example

import React from "react";
import { createMaterialBottomTabNavigator } from "@react-navigation/material-bottom-tabs";
import Ionicons from "react-native-vector-icons/Ionicons";
import { StyleSheet, View } from "react-native";
import HomeScreen from "../Screens/HomeScreen";
import SearchScreen from "../Screens/SearchScreen";
import PostScreen from "../Screens/PostScreen";
import MapScreen from "../Screens/MapScreen";
import ProfileScreen from "../Screens/ProfileScreen";

type TabBarIconProps = {
  focused: boolean;
  color: string;
};

const Tab = createMaterialBottomTabNavigator();

export default function Tabs() {
  return (
    <Tab.Navigator
      initialRouteName="Home"
      activeColor="#fff"
      barStyle={{ backgroundColor: "#1A1A23", ...styles.shadow }}
    >
      <Tab.Screen
        name="Home"
        component={HomeScreen}
        options={{
          tabBarLabel: "Home",
          tabBarIcon: ({ focused }: TabBarIconProps) => (
            <Ionicons
              name={focused ? "home-sharp" : "home-outline"}
              color={focused ? "#fff" : "#ffffff40"}
              size={26}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Search"
        component={SearchScreen}
        options={{
          tabBarLabel: "Search",
          tabBarIcon: ({ focused }: TabBarIconProps) => (
            <Ionicons
              name={focused ? "ios-search-sharp" : "search-outline"}
              color={focused ? "#fff" : "#ffffff40"}
              size={26}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Post"
        component={PostScreen}
        options={{
          tabBarLabel: "Post",
          tabBarIcon: ({ focused }: TabBarIconProps) => (
            <Ionicons
              name={focused ? "md-add-sharp" : "md-add-outline"}
              color={focused ? "#fff" : "#ffffff40"}
              size={26}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Map"
        component={MapScreen}
        options={{
          tabBarLabel: "Map",
          tabBarIcon: ({ focused }: TabBarIconProps) => (
            <Ionicons
              name={focused ? "location-sharp" : "location-outline"}
              color={focused ? "#fff" : "#ffffff40"}
              size={24}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Profile"
        component={ProfileScreen}
        options={{
          tabBarLabel: "Profile",
          tabBarIcon: ({ focused }: TabBarIconProps) => (
            <Ionicons
              name={focused ? "person-sharp" : "person-outline"}
              color={focused ? "#fff" : "#ffffff40"}
              size={25}
            />
          ),
        }}
      />
    </Tab.Navigator>
  );
}

const styles = StyleSheet.create({
  shadow: {
    shadowColor: "#ffe45d",
    shadowOffset: {
      width: 0,
      height: 10,
    },
    shadowOpacity: 0.25,
    shadowRadius: 3.5,
    elevation: 5,
  },
});

* Second: Simple Bottom Navigator

step A: Install @react-navigation/bottom-tabs package

npm install @react-navigation/bottom-tabs

step B: Create "BottomTab.tsx" file in "BottomTabs" folder

  • Import "CreateBottomTabNavigator" from @react-navigation/bottom-tabs

  • Import Ionic from react-native-vector-icons/Ionicons

  • Import the specific screens that you want to display

Try this example

import React from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import HomeScreen from "../Screens/HomeScreen";
import MapScreen from "../Screens/MapScreen";
import SearchScreen from "../Screens/SearchScreen";
import PostScreen from "../Screens/PostScreen";
import ProfileScreen from "../Screens/ProfileScreen";
import Ionic from "react-native-vector-icons/Ionicons";
import { View } from "react-native";

type RootTabParamList = {
  HomeScreen: undefined;
  SearchScreen: undefined;
  PostScreen: undefined;
  MapScreen: undefined;
  ProfileScreen: undefined;
};

const Tab = createBottomTabNavigator<RootTabParamList>();

const BottomTab: React.FC = () => {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarShowLabel: false,
        headerShown: false,
        tabBarStyle: {
          backgroundColor: "#1A1A23",
          borderTopEndRadius: 10,
          borderTopStartRadius: 10,
          position: "absolute",
          borderTopColor: "transparent",
          elevation: 0,
          height: 54,
          overflow: "hidden",
        },
        tabBarIcon: ({ focused, color }: { focused: boolean; color: string }) => {
          let iconName: string | undefined;
          let iconColor = focused ? "#ffffff" : "#ffffff40";

          switch (route.name) {
            case "HomeScreen":
              iconName = focused ? "home-sharp" : "home-outline";
              break;
            case "SearchScreen":
              iconName = focused ? "ios-search-sharp" : "search-outline";
              break;
            case "PostScreen":
              iconName = focused ? "md-add-sharp" : "md-add-outline";
              break;
            case "MapScreen":
              iconName = focused ? "location-sharp" : "location-outline";
              break;
            case "ProfileScreen":
              iconName = focused ? "person-sharp" : "person-outline";
              break;
            default:
              iconName = "ellipse";
          }

          return (
            <View style={{ alignItems: "center" }}>
              <Ionic
                name={iconName}
                style={{ marginBottom: 4 }}
                size={22}
                color={iconColor}
              />
              {focused && (
                <Ionic
                  name="ellipse"
                  size={4}
                  color="#ffffff"
                />
              )}
            </View>
          );
        },
      })}
    >
      <Tab.Screen name="HomeScreen" component={HomeScreen} />
      <Tab.Screen name="SearchScreen" component={SearchScreen} />
      <Tab.Screen name="PostScreen" component={PostScreen} />
      <Tab.Screen name="MapScreen" component={MapScreen} />
      <Tab.Screen name="ProfileScreen" component={ProfileScreen} />
    </Tab.Navigator>
  );
};

export default BottomTab;

* Third: Curved Base Navigator

step A: Install react-native-curved-bottom-bar package

npm i react-native-curved-bottom-bar react-native-svg

step B: Create "CurvedBottomTab.js" file in "BottomTabs" folder

  • Import "CreateBottomTabNavigator" from @react-navigation/bottom-tabs

  • Import Ionicons from react-native-vector-icons/Ionicons

  • Import the specific screens that you want to display

Try this example

import React from "react";
import { Animated, StyleSheet, TouchableOpacity, View } from "react-native";
import { CurvedBottomBarExpo } from "react-native-curved-bottom-bar";
import Ionicons from "react-native-vector-icons/Ionicons";
import { useNavigation, NavigationProp } from "@react-navigation/native";
import HomeScreen from "../Screens/HomeScreen";
import SearchScreen from "../Screens/SearchScreen";
import MapScreen from "../Screens/MapScreen";
import ProfileScreen from "../Screens/ProfileScreen";

type RootStackParamList = {
  Home: undefined;
  Search: undefined;
  Map: undefined;
  Profile: undefined;
  PostScreen: undefined;
};

const BaseNavigator: React.FC = () => {
  const navigation = useNavigation<NavigationProp<RootStackParamList>>();

  const _renderIcon = (routeName: string, selectedTab: string) => {
    let icon = "";

    switch (routeName) {
      case "Home":
        icon = "home";
        break;
      case "Search":
        icon = "business";
        break;
      case "Map":
        icon = "bookmark";
        break;
      case "profile":
        icon = "settings-sharp";
        break;
    }

    return (
      <Ionicons
        name={icon}
        size={25}
        color={routeName === selectedTab ? "#fff" : "#ffffff40"}
      />
    );
  };

  const renderTabBar = ({
    routeName,
    selectedTab,
    navigate,
  }: {
    routeName: string;
    selectedTab: string;
    navigate: (routeName: string) => void;
  }) => (
    <TouchableOpacity
      onPress={() => navigate(routeName)}
      style={{
        flex: 1,
        borderColor: "black",
        position: "relative",
        alignItems: "center",
        justifyContent: "center",
      }}
    >
      {_renderIcon(routeName, selectedTab)}
    </TouchableOpacity>
  );

  return (
    <View style={{ flex: 1 }}>
      <CurvedBottomBarExpo.Navigator
        style={styles.bottomBar}
        height={65}
        circleWidth={55}
        bgColor="#1A1A23"
        initialRouteName="Home"
        borderTopLeftRight
        renderCircle={({ selectedTab, navigate }) => (
          <Animated.View>
            <TouchableOpacity
              style={styles.btnCircle}
              onPress={() => navigation.navigate("PostScreen")}
            >
              <Ionicons name="add" color="white" size={25} />
            </TouchableOpacity>
          </Animated.View>
        )}
        tabBar={renderTabBar}
      >
        <CurvedBottomBarExpo.Screen
          name="Home"
          position="LEFT"
          options={{ headerShown: false }}
          component={HomeScreen}
        />
        <CurvedBottomBarExpo.Screen
          name="Search"
          accessible={true}
          accessibilityLabel="Get more from ManageHub"
          position="LEFT"
          options={{ headerShown: false }}
          component={SearchScreen}
        />
        <CurvedBottomBarExpo.Screen
          name="Map"
          position="RIGHT"
          options={{ headerShown: false }}
          component={MapScreen}
        />
        <CurvedBottomBarExpo.Screen
          name="profile"
          component={ProfileScreen}
          position="RIGHT"
          options={{ headerShown: false }}
        />
      </CurvedBottomBarExpo.Navigator>
    </View>
  );
};

export default BaseNavigator;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  button: {
    marginVertical: 5,
  },
  bottomBar: {
    position: "absolute",
    borderRadius: 20,
    elevation: 1000,
    shadowColor: "#000",
    shadowOffset: {
      width: 0,
      height: 0.5,
    },
    shadowOpacity: 0.2,
    shadowRadius: 1.41,
  },
  btnCircle: {
    width: 60,
    height: 60,
    borderRadius: 35,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "white",
    padding: 10,
    shadowColor: "#1A1A23",
    shadowOffset: {
      width: 0,
      height: 0.5,
    },
    shadowOpacity: 0.2,
    shadowRadius: 0.41,
    elevation: 1,
    bottom: 30,
  },
  imgCircle: {
    width: 30,
    height: 30,
    tintColor: "gray",
  },
  img: {
    width: 30,
    height: 30,
  },
});

Restart the Expo development server, and you'll discover an amazing base navigator waiting for you!

Click here to explore the project's source code on GitHub and see the incredible base navigator.