Bottom Tabs Navigator
See Native Bottom Tabs Navigator for a native implementation that uses native primitives on Android & iOS, including platform styling such as Liquid Glass on iOS >= 26.
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.
Installation
To use this navigator, ensure that you have @react-navigation/native and its dependencies (follow this guide), then install @react-navigation/bottom-tabs:
npm
yarn
pnpm
bun
npm install @react-navigation/bottom-tabs
yarn add @react-navigation/bottom-tabs
pnpm add @react-navigation/bottom-tabs
bun add @react-navigation/bottom-tabs
Usage
To use this navigator, import it from @react-navigation/bottom-tabs:
- Static
- Dynamic
import {
createBottomTabNavigator,
createBottomTabScreen,
} from '@react-navigation/bottom-tabs';
const MyTabs = createBottomTabNavigator({
screens: {
Home: createBottomTabScreen({
screen: HomeScreen,
}),
Profile: createBottomTabScreen({
screen: ProfileScreen,
}),
},
});
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>
);
}
API Definition
Props
In addition to the common props shared by all navigators, the bottom tab navigator accepts the following additional props:
backBehavior
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 ininitialRouteNameprop, if not passed, defaults to the first screenorder- return to screen defined before the focused screenhistory- return to last visited screen in the navigator; if the same screen is visited multiple times, the older entries are dropped from the historyfullHistory- return to last visited screen in the navigator; doesn't drop duplicate entries unlikehistory- this behavior is useful to match how web pages worknone- do not handle back button
detachInactiveScreens
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.
tabBar
Function that returns a React element to display as the tab bar.
The function receives an object containing the following properties as the argument:
state- The state object for the tab navigator.descriptors- The descriptors object containing options for the tab navigator.navigation- The navigation object for the tab navigator.
The state.routes array contains all the routes defined in the navigator. Each route's options can be accessed using descriptors[route.key].options.
Example:
- Static
- Dynamic
import { View, Platform } from 'react-native';
import { useLinkBuilder, useTheme } from '@react-navigation/native';
import { Text, PlatformPressable } from '@react-navigation/elements';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function MyTabBar({ state, descriptors, navigation }) {
const { colors } = useTheme();
const { buildHref } = useLinkBuilder();
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
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.name, route.params);
}
};
const onLongPress = () => {
navigation.emit({
type: 'tabLongPress',
target: route.key,
});
};
return (
<PlatformPressable
key={route.key}
href={buildHref(route.name, route.params)}
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarButtonTestID}
onPress={onPress}
onLongPress={onLongPress}
style={{ flex: 1 }}
>
<Text style={{ color: isFocused ? colors.primary : colors.text }}>
{label}
</Text>
</PlatformPressable>
);
})}
</View>
);
}
const MyTabs = createBottomTabNavigator({
tabBar: (props) => <MyTabBar {...props} />,
screens: {
Home: HomeScreen,
Profile: ProfileScreen,
},
});
import { View, Platform } from 'react-native';
import { useLinkBuilder, useTheme } from '@react-navigation/native';
import { Text, PlatformPressable } from '@react-navigation/elements';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
function MyTabBar({ state, descriptors, navigation }) {
const { colors } = useTheme();
const { buildHref } = useLinkBuilder();
return (
<View style={{ flexDirection: 'row' }}>
{state.routes.map((route, index) => {
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({