React NavigationReact NativeNavigation

Native Bottom Tabs in React Navigation: The Real Native Feel

← All posts·2025-03-10·4 min read

Native Bottom Tabs in React Navigation: The Real Native Feel

React Navigation's createNativeBottomTabNavigator is the tab navigator you should be using in 2025. Unlike the classic JavaScript-based tab bar, this one uses UITabBarController on iOS and BottomNavigationView on Android — meaning gestures, animations, and haptics all feel exactly like a first-party app.

Why Native Tabs?

The JS-based tab navigator renders a custom view that tries to mimic the platform tab bar. It works, but it's always slightly off — the transitions feel different, it doesn't respond to iOS 18's sidebar mode, and you miss out on SF Symbols.

Native tabs fixes all of this. The trade-off: you need a development build (not Expo Go), and Android is limited to 5 tabs.

Requirements

  • React Native 0.79+
  • Expo SDK 53+
  • react-native-screens (latest)
  • A development build — this won't work in Expo Go
npm install @react-navigation/bottom-tabs react-native-screens

Basic Setup

Dynamic API (recommended):

import { createNativeBottomTabNavigator } from "@react-navigation/bottom-tabs"; const Tab = createNativeBottomTabNavigator(); export default function AppTabs() { return ( <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Explore" component={ExploreScreen} /> <Tab.Screen name="Profile" component={ProfileScreen} /> </Tab.Navigator> ); }

Static API:

const MyTabs = createNativeBottomTabNavigator({ screens: { Home: HomeScreen, Explore: ExploreScreen, Profile: ProfileScreen, }, });

Icons

SF Symbols (iOS)

The cleanest way on iOS — no icon library needed:

<Tab.Screen name="Home" component={HomeScreen} options={{ tabBarIcon: { sfSymbol: "house.fill" }, }} />

Image icons (cross-platform)

import { Image } from "react-native"; <Tab.Screen name="Home" component={HomeScreen} options={{ tabBarIcon: ({ color, size }) => ( <Image source={require("./assets/home.png")} style={{ width: size, height: size, tintColor: color }} /> ), }} />

System items (iOS only)

options={{ tabBarSystemItem: "bookmarks", // search, favorites, history, etc. }}

Styling

<Tab.Navigator screenOptions={{ tabBarActiveTintColor: "#000", tabBarInactiveTintColor: "#999", // Android only tabBarStyle: { backgroundColor: "#fff", }, }} >

iOS blur effect:

screenOptions={{ tabBarBlurEffect: "systemMaterial", // iOS 18 and below }}

Badges

options={{ tabBarBadge: 3, // number tabBarBadge: "New", // or string }}

iOS 18+ Features

Sidebar mode

On iPad and large iPhones, the tab bar can transform into a sidebar:

<Tab.Navigator screenOptions={{ tabBarControllerMode: "tabSidebar" }}>

Minimizable tabs (iOS 26+)

Tabs collapse when the user scrolls down, giving more screen space:

options={{ tabBarMinimizeBehavior: "onScrollDown", }}

Bottom accessory (iOS 26+)

Add a custom view below the tab bar — great for a floating action button:

<Tab.Navigator screenOptions={{ bottomAccessory: () => <MyFloatingButton />, }} >

Platform Differences

FeatureiOSAndroid
Max tabsUnlimited5
SF Symbols
Blur effect✅ (iOS 18-)
Sidebar mode✅ (iOS 18+)
Active indicator
Inactive tintVia systemtabBarInactiveTintColor

Events

<Tab.Screen name="Home" component={HomeScreen} listeners={{ tabPress: (e) => { // Scroll to top, refresh data, etc. console.log("Tab pressed"); }, }} />

Pro Tips

1. Use popToTopOnBlur to reset navigation when leaving a tab:

screenOptions={{ popToTopOnBlur: true }}

2. Lazy loading is on by default — screens only mount when first visited. Disable if you need a screen to be always mounted:

options={{ lazy: false }}

3. Programmatic navigation:

import { useNavigation } from "@react-navigation/native"; const navigation = useNavigation(); navigation.jumpTo("Profile");

Conclusion

If you're building a serious React Native app in 2025, createNativeBottomTabNavigator should be your default. The native components give you real platform behavior for free — iOS sidebar mode, Liquid Glass on iOS 26, SF Symbols, and correct haptics. The only real constraint is the 5-tab Android limit, which is rarely a problem in practice.

Switch to a development build, drop in the native navigator, and your tab bar will finally feel like it belongs on the platform.