Skip to main content

Tab navigator

Perhaps the most common navigation style in mobile apps is tab-based navigation. These can be tabs at the bottom of the screen or at the top below the heading (or even instead of the heading).

This guide coverscreateBottomTabNavigator. You can also usecreateMaterialBottomTabNavigator or createMaterialTopTabNavigator to add tabs to your application.

Before proceeding, first install @response-navigation/bottom-tabs:

npm install @react-navigation/bottom-tabs@next

A minimal example of tab navigation

import * as React from 'react'
import { Text, View } from 'react-native'
import { NavigationContainer } from '@react-navigation/native'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'

const HomeScreen = () => (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
)

const SettingsScreen = () => (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
)

const Tab = createBottomTabNavigator()

export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
)
}

Try this example on Snack

Customizing appearance

This is similar to how you set up the stack navigator - some properties are set when the tab navigator is initialized, while others can be configured per screen in options.

// You can import Ionicons from @expo/vector-icons if you use Expo or
// react-native-vector-icons/Ionicons otherwise.
import * as React from 'react'
import { Text, View } from 'react-native'
import Ionicons from 'react-native-vector-icons/Ionicons'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { NavigationContainer } from '@react-navigation/native'

function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
)
}

function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
)
}

const Tab = createBottomTabNavigator()

export default function App() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName

if (route.name === 'Home') {
iconName = focused ? 'ios-information-circle' : 'ios-information-circle-outline'
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list'
}

// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />
},
tabBarActiveTintColor: 'tomato',
tabBarInactiveTintColor: 'gray'
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
)
}

Try this example on Snack

Let's break it down:

  • tabBarIcon is a supported option in the bottom tab navigator. So, we know we can use it in our screen components in the options prop, but in this case we decided to put it in the screenOptions prop in the Tab.Navigator to centralize the icon configuration for convenience.

  • tabBarIcon is a function that sets the state parameters focused, color and size. If you look further in the configuration, you will see tabBarOptions, activeTintColor and inactiveTintColor. The defaults are the defaults for the iOS platform, but you can change them here. The color that is passed to tabBarIcon can be active or inactive, depending on the state in focus (focused active). Size is the size of the icon expected by the tab bar.

  • Read the complete API reference for more information on the createBottomTabNavigator configuration options.

Add icons to icons

Sometimes we want to add icons to some icons. To do this, you can use the tabBarBadge parameter:

<Tab.Screen name="Home" component={HomeScreen} options={{ tabBarBadge: 3 }} />

Try this example on Snack

From a UI perspective, this component is ready to use, but you still need to find a way to properly pass the icon counter from somewhere else, for example with React Context, Redux, MobX or event emitters.

tabs

Switching between tabs

The familiar navigation.navigate API is used to switch from one tab to another.

const HomeScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('Settings')}
/>
</View>
)
}

const SettingsScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
)
}

Try this example on Snack

Stack navigator for each tab

Usually, tabs don't just display one screen - for example, in your Twitter feed, you can click on a tweet and it will take you to a new screen inside that tab with all the replies. You can think of this as having separate navigation stacks inside each tab, and this is how we will model them in React Navigation.

import * as React from 'react'
import { Button, Text, View } from 'react-native'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'

const DetailsScreen = () => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
)
}

const HomeScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
)
}

const SettingsScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
)
}

const HomeStack = createStackNavigator()

const HomeStackScreen = () => {
return (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
)
}

const SettingsStack = createStackNavigator()

const SettingsStackScreen = () => {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Details" component={DetailsScreen} />
</SettingsStack.Navigator>
)
}

const Tab = createBottomTabNavigator();

const App = () => {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
</Tab.Navigator>
</NavigationContainer>
)
}

export default App

Try this example on Snack

Done ✅

To see how well you learned this lesson, take the test in our school's mobile app on this topic or in Telegram bot.

Sumerian school

React Navigation

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Dmitriy Vasilev

📖💲

Become a Patron!