Bottom Tab Navigator
Tab navigators let users switch between top-level sections of your app with a single tap. The Bottom Tab Navigator renders a tab bar at the bottom of the screen — the pattern you see in apps like Twitter, Instagram, and Spotify.
Creating a Tab Navigator
The setup mirrors what we did with the stack navigator. Import createBottomTabNavigator and create an instance:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
Adding Screens
Define your tab screens inside Tab.Navigator:
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { View, Text, StyleSheet } from 'react-native';
const Tab = createBottomTabNavigator();
function HomeScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Home</Text>
</View>
);
}
function SearchScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Search</Text>
</View>
);
}
function ProfileScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Profile</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
title: { fontSize: 24 },
});
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
Each Tab.Screen becomes a tab at the bottom. Tapping a tab switches to that screen instantly — no push/pop animation like a stack. The tab bar persists across all screens.
Adding Icons
Tabs without icons look bare. Use @expo/vector-icons (included with Expo) to add them:
import { Ionicons } from '@expo/vector-icons';
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'Search') {
iconName = focused ? 'search' : 'search-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
The tabBarIcon function receives focused (whether this tab is active), color (the active or inactive tint), and size (the recommended icon size). Return any React element — here we use Ionicons but you could use any icon library or a custom component.
Adding Badges
Show a notification count on a tab with tabBarBadge:
<Tab.Screen
name="Home"
component={HomeScreen}
options={{ tabBarBadge: 3 }}
/>
This renders a small red badge with "3" on the Home tab icon. Pass undefined or omit the option to remove the badge.
Complete Example
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { View, Text, StyleSheet } from 'react-native';
import { Ionicons } from '@expo/vector-icons';
const Tab = createBottomTabNavigator();
function HomeScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Home</Text>
</View>
);
}
function SearchScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Search</Text>
</View>
);
}
function ProfileScreen() {
return (
<View style={styles.container}>
<Text style={styles.title}>Profile</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, alignItems: 'center', justifyContent: 'center' },
title: { fontSize: 24 },
});
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'home' : 'home-outline';
} else if (route.name === 'Search') {
iconName = focused ? 'search' : 'search-outline';
} else if (route.name === 'Profile') {
iconName = focused ? 'person' : 'person-outline';
}
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} options={{ tabBarBadge: 3 }} />
<Tab.Screen name="Search" component={SearchScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
Three tabs with filled/outline icons that toggle based on focus, plus a badge on the Home tab. In the next lesson we'll customize the tab bar's appearance and build a custom tab bar component.