HomeGuidesReferenceLearn
ArchiveExpo SnackDiscord and ForumsNewsletter

Tabs

Learn how to use the Tabs layout in Expo Router.


Tabs are a common way to navigate between different sections of an app. Expo Router provides a tabs layout to help you create a tab bar at the bottom of your app. The fastest way to get started is to use a template. See the quick start installation to get started.

Continue reading to add tabs to an existing project or to customize your app's tabs.

Get started

You can use file-based routing to create a tabs layout. Here's an example file structure:

app
 _layout.tsx
 (tabs)
  _layout.tsx
  index.tsx
  settings.tsx

This file structure will produce a layout with a tab bar at the bottom of the screen. The tab bar will have two tabs, "Home" and "Settings":

You can use the app/_layout.tsx file to define your app's main navigator:

app/_layout.tsx
import { Stack } from 'expo-router/stack';

export default function AppLayout() {
  return (
    <Stack>
      <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
    </Stack>
  );
}

The (tabs) directory is a special directory name that tells Expo Router to use the Tabs layout.

From the example, the (tabs) directory has three files. The first is (tabs)/_layout.tsx. This file is the main layout file for the tab bar and each tab. Inside it, you can control how the tab bar and each tab button look and behave.

app/(tabs)/_layout.tsx
import React from 'react';
import FontAwesome from '@expo/vector-icons/FontAwesome';
import { Tabs } from 'expo-router';

export default function TabLayout() {
  return (
    <Tabs screenOptions={{ tabBarActiveTintColor: 'blue' }}>
      <Tabs.Screen
        name="index"
        options={{
          title: 'Home',
          tabBarIcon: ({ color }) => <FontAwesome size={28} name="home" color={color} />,
        }}
      />
      <Tabs.Screen
        name="settings"
        options={{
          title: 'Settings',
          tabBarIcon: ({ color }) => <FontAwesome size={28} name="cog" color={color} />,
        }}
      />
    </Tabs>
  );
}

The tabs layout wraps the Bottom Tabs Navigator from React Navigation. You can use the options presented in the React Navigation documentation to customize the tab bar.

Finally, we have the two tab files that make up the content of the tabs: app/(tabs)/index.tsx and app/(tabs)/settings.tsx.

app/(tabs)/index.tsx & app/(tabs)/settings.tsx
import { View, Text } from 'react-native';

export default function Tab() {
  return (
    <View style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
      <Text>Tab [Home|Settings]</Text>
    </View>
  );
}

The tab file named index.tsx will become the default tab when the app is loaded. We made the second tab file settings.tsx to show how you can add more tabs to the tab bar.

Advanced

Hiding a tab

Sometimes you want a route to exist but not show up in the tab bar, you can pass href: null to disable the button:

app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router/tabs';

export default function AppLayout() {
  return (
    <Tabs>
      <Tabs.Screen
        // Name of the route to hide.
        name="index"
        options={{
          // This tab will no longer show up in the tab bar.
          href: null,
        }}
      />
    </Tabs>
  );
}

Dynamic routes

You may want to use a dynamic route in your tab bar (for example, a profile tab). For this case, you'll want the button to always link to a specific href.

app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router/tabs';

export default function AppLayout() {
  return (
    <Tabs>
      <Tabs.Screen
        // Name of the dynamic route.
        name="[user]"
        options={{
          // Ensure the tab always links to the same href.
          href: '/evanbacon',
          // OR you can use the href object:
          href: {
            pathname: '/[user]',
            params: {
              user: 'evanbacon',
            },
          },
        }}
      />
    </Tabs>
  );
}