Skip to main content
Version: 6.x

Bottom Tabs Navigator

A simple tab bar on the bottom of the screen that lets you switch between different routes. Routes are lazily initialized -- their screen components are not mounted until they are first focused.


To use this navigator, ensure that you have @react-navigation/native and its dependencies (follow this guide), then install @react-navigation/bottom-tabs:

npm install @react-navigation/bottom-tabs

API Definition

To use this tab navigator, import it from @react-navigation/bottom-tabs:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

function MyTabs() {
return (
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />

For a complete usage guide please visit Tab Navigation


The Tab.Navigator component accepts following props:


Optional unique ID for the navigator. This can be used with navigation.getParent to refer to this navigator in a child navigator.


The name of the route to render on first load of the navigator.


Default options to use for the screens in the navigator.


This controls what happens when goBack is called in the navigator. This includes pressing the device's back button or back gesture on Android.

It supports the following values:

  • firstRoute - return to the first screen defined in the navigator (default)
  • initialRoute - return to initial screen passed in initialRouteName prop, if not passed, defaults to the first screen
  • order - return to screen defined before the focused screen
  • history - return to last visited screen in the navigator; if the same screen is visited multiple times, the older entries are dropped from the history
  • none - do not handle back button


Boolean used to indicate whether inactive screens should be detached from the view hierarchy to save memory. This enables integration with react-native-screens. Defaults to true.


Style object for the component wrapping the screen content.


Function that returns a React element to display as the tab bar.


import { View, Text, TouchableOpacity } from 'react-native';

function MyTabBar({ state, descriptors, navigation }) {
return (
<View style={{ flexDirection: 'row' }}>
{, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title

const isFocused = state.index === index;

const onPress = () => {
const event = navigation.emit({
type: 'tabPress',
target: route.key,
canPreventDefault: true,

if (!isFocused && !event.defaultPrevented) {
navigation.navigate(, route.params);

const onLongPress = () => {
type: 'tabLongPress',
target: route.key,

return (
accessibilityState={isFocused ? { selected: true } : {}}
style={{ flex: 1 }}
<Text style={{ color: isFocused ? '#673ab7' : '#222' }}>

// ...

<Tab.Navigator tabBar={props => <MyTabBar {...props} />}>

This example will render a basic tab bar with labels.

Note that you cannot use the useNavigation hook inside the tabBar since useNavigation is only available inside screens. You get a navigation prop for your tabBar which you can use instead:

function MyTabBar({ navigation }) {
return (
title="Go somewhere"
onPress={() => {
// Navigate using the `navigation` prop that you received


The following options can be used to configure the screens in the navigator. These can be specified under screenOptions prop of Tab.navigator or options prop of Tab.Screen.


Generic title that can be used as a fallback for headerTitle and tabBarLabel.


Title string of a tab displayed in the tab bar or a function that given { focused: boolean, color: string } returns a React.Node, to display in tab bar. When undefined, scene title is used. To hide, see tabBarShowLabel.


Whether the tab label should be visible. Defaults to true.


Whether the label is shown below the icon or beside the icon.

  • below-icon: the label is shown below the icon (typical for iPhones)
  • beside-icon the label is shown next to the icon (typical for iPad)

By default, the position is chosen automatically based on device width.


Style object for the tab label.


Function that given { focused: boolean, color: string, size: number } returns a React.Node, to display in the tab bar.


Style object for the tab icon.


Text to show in a badge on the tab icon. Accepts a string or a number.


Style for the badge on the tab icon. You can specify a background color or text color here.


Accessibility label for the tab button. This is read by the screen reader when the user taps the tab. It's recommended to set this if you don't have a label for the tab.


ID to locate this tab button in tests.


Function which returns a React element to render as the tab bar button. It wraps the icon and label. Renders Pressable by default.

You can specify a custom implementation here:

tabBarButton: (props) => <TouchableOpacity {...props} />;


Color for the icon and label in the active tab.


Color for the icon and label in the inactive tabs.


Background color for the active tab.


Background color for the inactive tabs.


Whether the tab bar is hidden when the keyboard opens. Defaults to false.


Style object for the tab item container.


Style object for the tab bar. You can configure styles such as background color here.

To show your screen under the tab bar, you can set the position style to absolute:

tabBarStyle: { position: 'absolute' },

You also might need to add a bottom margin to your content if you have a absolutely positioned tab bar. React Navigation won't do it automatically.

To get the height of the bottom tab bar, you can use BottomTabBarHeightContext with React's Context API or useBottomTabBarHeight:

import { BottomTabBarHeightContext } from '@react-navigation/bottom-tabs';

// ...

{tabBarHeight => (
/* render something */


import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';

// ...

const tabBarHeight = useBottomTabBarHeight();


Function which returns a React Element to use as background for the tab bar. You could render an image, a gradient, blur view etc.:

import { BlurView } from 'expo-blur';

// ...

tabBarStyle: { position: 'absolute' },
tabBarBackground: () => (
<BlurView tint="light" intensity={100} style={StyleSheet.absoluteFill} />

When using BlurView, make sure to set position: 'absolute' in tabBarStyle as well. You'd also need to use useBottomTabBarHeight() to add a bottom padding to your content.


Whether this screens should render the first time it's accessed. Defaults to true. Set it to false if you want to render the screen on initial render.


Whether this screen should be unmounted when navigating away from it. Unmounting a screen resets any local state in the screen as well as state of nested navigators in the screen. Defaults to false.

Normally, we don't recommend enabling this prop as users don't expect their navigation history to be lost when switching tabs. If you enable this prop, please consider if this will actually provide a better experience for the user.


Boolean indicating whether to prevent inactive screens from re-rendering. Defaults to false. Defaults to true when enableFreeze() from react-native-screens package is run at the top of the application.

Requires react-native-screens version >=3.16.0.

Only supported on iOS and Android.

You can find the list of header related options here. These options can be specified under screenOptions prop of Tab.navigator or options prop of Tab.Screen. You don't have to be using @react-navigation/elements directly to use these options, they are just documented in that page.

In addition to those, the following options are also supported in bottom tabs:

Custom header to use instead of the default header.

This accepts a function that returns a React Element to display as a header. The function receives an object containing the following properties as the argument:

  • navigation - The navigation object for the current screen.
  • route - The route object for the current screen.
  • options - The options for the current screen
  • layout - Dimensions of the screen, contains height and width properties.


import { getHeaderTitle } from '@react-navigation/elements';

// ..

header: ({ navigation, route, options }) => {
const title = getHeaderTitle(options,;

return <MyHeader title={title} style={options.headerStyle} />;

To set a custom header for all the screens in the navigator, you can specify this option in the screenOptions prop of the navigator.

Specify a height in headerStyle

If your custom header's height differs from the default header height, then you might notice glitches due to measurement being async. Explicitly specifying the height will avoid such glitches.


headerStyle: {
height: 80, // Specify the height of your custom header

Note that this style is not applied to the header by default since you control the styling of your custom header. If you also want to apply this style to your header, use options.headerStyle from the props.


Whether to show or hide the header for the screen. The header is shown by default. Setting this to false hides the header.


The navigator can emit events on certain actions. Supported events are:


This event is fired when the user presses the tab button for the current screen in the tab bar. By default a tab press does several things:

  • If the tab is not focused, tab press will focus that tab
  • If the tab is already focused:
    • If the screen for the tab renders a scroll view, you can use useScrollToTop to scroll it to top
    • If the screen for the tab renders a stack navigator, a popToTop action is performed on the stack

To prevent the default behavior, you can call event.preventDefault:

React.useEffect(() => {
const unsubscribe = navigation.addListener('tabPress', (e) => {
// Prevent default behavior

// Do something manually
// ...

return unsubscribe;
}, [navigation]);

If you have a custom tab bar, make sure to emit this event.


This event is fired when the user presses the tab button for the current screen in the tab bar for an extended period. If you have a custom tab bar, make sure to emit this event.


React.useEffect(() => {
const unsubscribe = navigation.addListener('tabLongPress', (e) => {
// Do something

return unsubscribe;
}, [navigation]);


The tab navigator adds the following methods to the navigation prop:


Navigates to an existing screen in the tab navigator. The method accepts following arguments:

  • name - string - Name of the route to jump to.
  • params - object - Screen params to use for the destination route.
navigation.jumpTo('Profile', { owner: 'Michaś' });


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

const Tab = createBottomTabNavigator();

function MyTabs() {
return (
tabBarActiveTintColor: '#e91e63',
tabBarLabel: 'Home',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
tabBarLabel: 'Updates',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="bell" color={color} size={size} />
tabBarBadge: 3,
tabBarLabel: 'Profile',
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="account" color={color} size={size} />