React Native course ยท Module 3: Navigation

Tab Navigation - Underwater Menu Tabs

3 min read ยท
In this lesson7

In the palace of Atlantis there is a main menu with tabs, allowing you to quickly move between the main sections. This is Tab Navigation!

Installing Tab Navigator

npx expo install @react-navigation/bottom-tabs

Basic Tab Navigator

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';

type TabParamList = {
  Home: undefined;
  Search: undefined;
  Profile: undefined;
  Settings: undefined;
};

const Tab = createBottomTabNavigator<TabParamList>();

function MainTabs() {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          let iconName: keyof typeof Ionicons.glyphMap;

          switch (route.name) {
            case 'Home':
              iconName = focused ? 'home' : 'home-outline';
              break;
            case 'Search':
              iconName = focused ? 'search' : 'search-outline';
              break;
            case 'Profile':
              iconName = focused ? 'person' : 'person-outline';
              break;
            case 'Settings':
              iconName = focused ? 'settings' : 'settings-outline';
              break;
            default:
              iconName = 'ellipse';
          }

          return <Ionicons name={iconName} size={size} color={color} />;
        },
        tabBarActiveTintColor: '#1a5276',
        tabBarInactiveTintColor: 'gray',
      })}
    >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Search" component={SearchScreen} />
      <Tab.Screen name="Profile" component={ProfileScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

Styling the Tab Bar

<Tab.Navigator
  screenOptions={{
    tabBarStyle: {
      backgroundColor: '#0a2e4a',
      borderTopWidth: 0,
      elevation: 10,
      height: 60,
      paddingBottom: 8,
      paddingTop: 8,
    },
    tabBarActiveTintColor: '#00d4ff',
    tabBarInactiveTintColor: '#6c7a89',
    tabBarLabelStyle: {
      fontSize: 12,
      fontWeight: '600',
    },
    headerStyle: {
      backgroundColor: '#0a2e4a',
    },
    headerTintColor: '#fff',
  }}
>
  {/* Screens */}
</Tab.Navigator>

Badge on a Tab

<Tab.Screen
  name="Notifications"
  component={NotificationsScreen}
  options={{
    tabBarBadge: 3, // Shows a badge with a number
    tabBarBadgeStyle: {
      backgroundColor: '#ff6b6b',
      color: '#fff',
    },
  }}
/>

Hiding the Tab Bar on Certain Screens

// In the screen component
import { useLayoutEffect } from 'react';

function DetailsScreen({ navigation }) {
  useLayoutEffect(() => {
    navigation.getParent()?.setOptions({
      tabBarStyle: { display: 'none' },
    });

    return () => {
      navigation.getParent()?.setOptions({
        tabBarStyle: { display: 'flex' },
      });
    };
  }, [navigation]);

  return <View>{/* content */}</View>;
}

Nesting Stack in Tabs

// Each tab can have its own Stack Navigator
function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="HomeMain" component={HomeScreen} />
      <Stack.Screen name="HomeDetails" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen
          name="Home"
          component={HomeStack}
          options={{ headerShown: false }} // Hide Tab header, Stack has its own
        />
        <Tab.Screen name="Profile" component={ProfileStack} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Top Tabs (Material Top Tabs)

npx expo install @react-navigation/material-top-tabs react-native-pager-view
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';

const TopTab = createMaterialTopTabNavigator();

function ProfileTabs() {
  return (
    <TopTab.Navigator
      screenOptions={{
        tabBarLabelStyle: { fontSize: 14, fontWeight: 'bold' },
        tabBarStyle: { backgroundColor: '#0a2e4a' },
        tabBarActiveTintColor: '#00d4ff',
        tabBarIndicatorStyle: { backgroundColor: '#00d4ff' },
      }}
    >
      <TopTab.Screen name="Posts" component={PostsScreen} />
      <TopTab.Screen name="Photos" component={PhotosScreen} />
      <TopTab.Screen name="Likes" component={LikesScreen} />
    </TopTab.Navigator>
  );
}

Tab Navigation is ideal for the main sections of an application. Users expect it at the bottom of the screen (iOS) or at the top (Android Material Design).

Code for this lesson: App.tsx
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';

const Tab = createBottomTabNavigator();

function Screen({ label }) {
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>{label}</Text>
    </View>
  );
}

const HomeScreen = () => <Screen label="Main Hall" />;
const MapScreen = () => <Screen label="Map of the Depths" />;
const ProfileScreen = () => <Screen label="Triton's Profile" />;

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        {/* TODO: add a "Home" tab with component={HomeScreen} */}
        {/* In options set tabBarIcon: ({ color, size }) => <Ionicons name="home" size={size} color={color} /> */}

        {/* TODO: add a "Map" tab (component={MapScreen}, icon "map") */}

        {/* TODO: add a "Profile" tab (component={ProfileScreen}, icon "person") */}

      </Tab.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#1a5276',
  },
  title: {
    fontSize: 22,
    color: '#fff',
    fontWeight: '600',
  },
});

Docs entries used in this lesson

Spotted a mistake in this lesson?

Check yourself

Answer the questions from this lesson. Pick an answer to see right away whether it is correct.

  1. 1. Which library is used to create bottom tabs?

  2. 2. Which property adds a badge (notification count) on a tab?

These are 2 of 3 questions for this lesson. Solve the rest in the game.

Hands-on tasks in the game

  • Horizontal ordering

    Arrange the correct tabBarIcon structure:

  • Code editor

    Complete the Tab Navigator code.

Useful articles