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.