Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Phase 6 · 8 / 10Tabs
Phase 6React Native with Expo
10 topics · 6–8 wks
  1. 1Your first Expo app
  2. 2View, Text and Image
  3. 3Pressable and TextInput
  4. 4Styling and flexbox on mobile
  5. 5Lists with FlatList
  6. 6Safe areas and the keyboard
  7. 7Screens and navigation
  8. 8Tabs
  9. 9Saving data on the phone
  10. 10Calling an API
JourneyPhase 6Tabs
01 / 09Overview

Tabs

You'll learn to add a bottom tab bar with Expo Router, with a title and an icon for each tab.

Why it mattersYour habit tracker gets two main sections, Today and Stats, and tabs let you jump between them with one tap.
about 60 min·needs: Screens and navigation
02 / 09

Watch & read

Start with the required ones. The others are there when you need them.

Docs
Expo tutorial: add a bottom tab navigatordocs.expo.dev · official tutorial · 15 min · English
MMamun's noteThe same tutorial page as last topic. Now read from "Add a bottom tab navigator" to the end. It moves the screens into a (tabs) folder, adds Ionicons and colours the active tab.
Video
Using a tab navigator with Expo RouterYouTube · Expo · 6 min · English
MMamun's noteWatch 0:00–5:43: the tabs layout, tab bar icons, labels and titles, hiding a screen with href: null, and badges. Then stop. The rest, a stack inside a tab, is useful later.
DocsOptional
JavaScript tabsdocs.expo.dev · official docs · 10 min · English
MMamun's noteRead "Get started with JavaScript tabs" and "Hiding a tab". Keep the page for later: "Tab bar options" lists every setting.
VideoOptional
How to add navigation to your app with Expo RouterYouTube · Expo · 8 min · English
MMamun's noteThe video version of the tutorial page. Watch 8:36–16:39: it adds the bottom tabs, then changes their colours and icons.
03 / 09

Explanation

A stack is for going deeper: list, then details, then edit. Tabs are for sections that are always one tap away, side by side. Think of the bar at the bottom of Facebook or bKash: Home, Search, Inbox. You don't go "back" from one to another. You just switch.

In Expo Router, tabs are a folder with a _layout.jsx that returns <Tabs>:

src/app/_layout.jsx <Stack>: the whole app
src/app/(tabs)/_layout.jsx <Tabs>: the tab bar
src/app/(tabs)/index.jsx first tab, Today, route "/"
src/app/(tabs)/stats.jsx second tab, Stats, route "/stats"
src/app/habit/[id].jsx opens on top of the tabs

The brackets in (tabs) make a group. The folder name does not appear in the route, so (tabs)/stats.jsx is just /stats. Every file in the folder becomes a tab, even ones you don't list.

<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432" }}>
<Tabs.Screen name="index" options={{ title: "Today" }} />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
</Tabs>

Tabs.Screen sets the order and options for one tab. name is the file name without .jsx. tabBarIcon draws the icon: a function that gets color (and focused) and returns an icon. The Expo tutorial uses Ionicons from @expo/vector-icons: <Ionicons name="today" color={color} size={24} />. Browse the names at icons.expo.fyi. Expo has said it will move to the @react-native-vector-icons packages later; the way you use an icon stays the same.

The root _layout.jsx is still a Stack, with the tabs as its first screen and their header hidden. That is why a habit's details open on top of the tab bar and Back returns to the tab you were on.

A brand new Expo project uses native tabs (NativeTabs), which draw the phone's own tab bar. You'll see them in the template. The ideas are the same; we use Tabs because the tutorial and most videos do.

People often name the file and the screen differently. stats.jsx with <Tabs.Screen name="Stats"> does not match (names are case-sensitive). Expo Router warns that no route has that name, and the tab shows without your title and icon. Use the exact file name.

When you read tabs, list the files in the (tabs) folder: that is your tab bar. Then read _layout.jsx for the order, titles and icons.

Words to recognise
Tabs(tabs)Tabs.ScreentabBarIconIonicons
04 / 09

Code tour

Click a line number with a ring to read the note for that line.

src/app/(tabs)/_layout.jsx5 notes
import Ionicons from "@expo/vector-icons/Ionicons";
Mentor note · line 1
One icon set, Ionicons. Browse its names at icons.expo.fyi.
2import { Tabs } from "expo-router";
3export default function TabLayout() {
4 return (
<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432", headerShown: false }}>
6 <Tabs.Screen
name="index"
8 options={{
9 title: "Today",
tabBarIcon: ({ color }) => <Ionicons name="today" color={color} size={24} />,
11 }}
12 />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
14 </Tabs>
15 );
16}
05 / 09

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 2
1// Files in src/app/(tabs):
2// _layout.jsx
3// index.jsx
4// stats.jsx
5// settings.jsx
6
7// src/app/(tabs)/_layout.jsx
8export default function TabLayout() {
9 return (
10 <Tabs>
11 <Tabs.Screen name="index" options={{ title: "Today" }} />
12 <Tabs.Screen name="stats" options={{ title: "Stats" }} />
13 </Tabs>
14 );
15}
How many tabs appear at the bottom?
DrillAdd tabs with icons2 / 2
This Snack uses React Navigation's bottom tabs, the same tab bar Expo Router's Tabs gives you. Give both tabs an icon, colour the active tab, and add a third Settings tab.
1import Ionicons from "@expo/vector-icons/Ionicons";
2import { NavigationContainer } from "@react-navigation/native";
3import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
4import { StyleSheet, Text, View } from "react-native";
5
6const Tab = createBottomTabNavigator();

Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.

Working whenThe Stats tab has an icon too. Try the Ionicons name "stats-chart".The active tab is lime green. Add screenOptions={{ tabBarActiveTintColor: "#C6F432" }} to the navigator.A third tab, Settings, shows its own screen and icon.
Check each goal yourself, then mark it.
06 / 09

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3What is the route of src/app/(tabs)/stats.jsx?
  2. 2 / 3Which part of a habit tracker fits tabs best?
  3. 3 / 3In tabBarIcon: ({ color }) => <Ionicons name="today" color={color} size={24} />, where does color come from?
07 / 09

Explain it back

Only you can see this. Log in to keep it.0 words
08 / 09

How confident are you with Tabs?

09 / 09

Done

You can now
Read a (tabs) folder and its _layout.jsx and say which tabs appear, in what order, with which icons.
Next: Saving data on the phone Back to Phase 6
On this page
  1. 01Tabs
  2. 02Watch & read
  3. 03Explanation
  4. 04Code tour
  5. 05Practice
  6. 06Quick check
  7. 07Explain it back
  8. 08Confidence
  9. 09Done
Up next · 02 / 09Watch & read
Mamun Labs LearnFound a mistake on this page? Tell Mamun.
Mamun Labs Learn
JourneyGlossary
esc
  • Try “map”, “flexbox” or “state”.
Log in
Start learning
Log in to save your progress. Everything here works without an account.Log in to save progressLog in
Phase 6React Native with Expo
10 topics · 6–8 wks
  1. 1Your first Expo app
  2. 2View, Text and Image
  3. 3Pressable and TextInput
  4. 4Styling and flexbox on mobile
  5. 5Lists with FlatList
  6. 6Safe areas and the keyboard
  7. 7Screens and navigation
  8. 8Tabs
  9. 9Saving data on the phone
  10. 10Calling an API
JourneyPhase 6Tabs
01 / 09Overview

Tabs

You'll learn to add a bottom tab bar with Expo Router, with a title and an icon for each tab.

Why it mattersYour habit tracker gets two main sections, Today and Stats, and tabs let you jump between them with one tap.
about 60 min·needs: Screens and navigation
02 / 09

Watch & read

Start with the required ones. The others are there when you need them.

Docs
Expo tutorial: add a bottom tab navigatordocs.expo.dev · official tutorial · 15 min · English
MMamun's noteThe same tutorial page as last topic. Now read from "Add a bottom tab navigator" to the end. It moves the screens into a (tabs) folder, adds Ionicons and colours the active tab.
Video
Using a tab navigator with Expo RouterYouTube · Expo · 6 min · English
MMamun's noteWatch 0:00–5:43: the tabs layout, tab bar icons, labels and titles, hiding a screen with href: null, and badges. Then stop. The rest, a stack inside a tab, is useful later.
DocsOptional
JavaScript tabsdocs.expo.dev · official docs · 10 min · English
MMamun's noteRead "Get started with JavaScript tabs" and "Hiding a tab". Keep the page for later: "Tab bar options" lists every setting.
VideoOptional
How to add navigation to your app with Expo RouterYouTube · Expo · 8 min · English
MMamun's noteThe video version of the tutorial page. Watch 8:36–16:39: it adds the bottom tabs, then changes their colours and icons.
03 / 09

Explanation

A stack is for going deeper: list, then details, then edit. Tabs are for sections that are always one tap away, side by side. Think of the bar at the bottom of Facebook or bKash: Home, Search, Inbox. You don't go "back" from one to another. You just switch.

In Expo Router, tabs are a folder with a _layout.jsx that returns <Tabs>:

src/app/_layout.jsx <Stack>: the whole app
src/app/(tabs)/_layout.jsx <Tabs>: the tab bar
src/app/(tabs)/index.jsx first tab, Today, route "/"
src/app/(tabs)/stats.jsx second tab, Stats, route "/stats"
src/app/habit/[id].jsx opens on top of the tabs

The brackets in (tabs) make a group. The folder name does not appear in the route, so (tabs)/stats.jsx is just /stats. Every file in the folder becomes a tab, even ones you don't list.

<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432" }}>
<Tabs.Screen name="index" options={{ title: "Today" }} />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
</Tabs>

Tabs.Screen sets the order and options for one tab. name is the file name without .jsx. tabBarIcon draws the icon: a function that gets color (and focused) and returns an icon. The Expo tutorial uses Ionicons from @expo/vector-icons: <Ionicons name="today" color={color} size={24} />. Browse the names at icons.expo.fyi. Expo has said it will move to the @react-native-vector-icons packages later; the way you use an icon stays the same.

The root _layout.jsx is still a Stack, with the tabs as its first screen and their header hidden. That is why a habit's details open on top of the tab bar and Back returns to the tab you were on.

A brand new Expo project uses native tabs (NativeTabs), which draw the phone's own tab bar. You'll see them in the template. The ideas are the same; we use Tabs because the tutorial and most videos do.

People often name the file and the screen differently. stats.jsx with <Tabs.Screen name="Stats"> does not match (names are case-sensitive). Expo Router warns that no route has that name, and the tab shows without your title and icon. Use the exact file name.

When you read tabs, list the files in the (tabs) folder: that is your tab bar. Then read _layout.jsx for the order, titles and icons.

Words to recognise
Tabs(tabs)Tabs.ScreentabBarIconIonicons
04 / 09

Code tour

Click a line number with a ring to read the note for that line.

src/app/(tabs)/_layout.jsx5 notes
import Ionicons from "@expo/vector-icons/Ionicons";
Mentor note · line 1
One icon set, Ionicons. Browse its names at icons.expo.fyi.
2import { Tabs } from "expo-router";
3export default function TabLayout() {
4 return (
<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432", headerShown: false }}>
6 <Tabs.Screen
name="index"
8 options={{
9 title: "Today",
tabBarIcon: ({ color }) => <Ionicons name="today" color={color} size={24} />,
11 }}
12 />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
14 </Tabs>
15 );
16}
05 / 09

Practice

Short drills. Take your time and read the code before you answer.

DrillPredict1 / 2
1// Files in src/app/(tabs):
2// _layout.jsx
3// index.jsx
4// stats.jsx
5// settings.jsx
6
7// src/app/(tabs)/_layout.jsx
8export default function TabLayout() {
9 return (
10 <Tabs>
11 <Tabs.Screen name="index" options={{ title: "Today" }} />
12 <Tabs.Screen name="stats" options={{ title: "Stats" }} />
13 </Tabs>
14 );
15}
How many tabs appear at the bottom?
DrillAdd tabs with icons2 / 2
This Snack uses React Navigation's bottom tabs, the same tab bar Expo Router's Tabs gives you. Give both tabs an icon, colour the active tab, and add a third Settings tab.
1import Ionicons from "@expo/vector-icons/Ionicons";
2import { NavigationContainer } from "@react-navigation/native";
3import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
4import { StyleSheet, Text, View } from "react-native";
5
6const Tab = createBottomTabNavigator();

Runs in the browser. Choose “My Device” in Snack to try it on your phone with Expo Go.

Working whenThe Stats tab has an icon too. Try the Ionicons name "stats-chart".The active tab is lime green. Add screenOptions={{ tabBarActiveTintColor: "#C6F432" }} to the navigator.A third tab, Settings, shows its own screen and icon.
Check each goal yourself, then mark it.
06 / 09

Quick check

3 questions. Each one explains itself after you answer.

  1. 1 / 3What is the route of src/app/(tabs)/stats.jsx?
  2. 2 / 3Which part of a habit tracker fits tabs best?
  3. 3 / 3In tabBarIcon: ({ color }) => <Ionicons name="today" color={color} size={24} />, where does color come from?
07 / 09

Explain it back

Only you can see this. Log in to keep it.0 words
08 / 09

How confident are you with Tabs?

09 / 09

Done

You can now
Read a (tabs) folder and its _layout.jsx and say which tabs appear, in what order, with which icons.
Next: Saving data on the phone Back to Phase 6
On this page
  1. 01Tabs
  2. 02Watch & read
  3. 03Explanation
  4. 04Code tour
  5. 05Practice
  6. 06Quick check
  7. 07Explain it back
  8. 08Confidence
  9. 09Done
Up next · 02 / 09Watch & read

A stack is for going deeper: list, then details, then edit. Tabs are for sections that are always one tap away, side by side. Think of the bar at the bottom of Facebook or bKash: Home, Search, Inbox. You don't go "back" from one to another. You just switch.

In Expo Router, tabs are a folder with a _layout.jsx that returns <Tabs>:

src/app/_layout.jsx <Stack>: the whole app
src/app/(tabs)/_layout.jsx <Tabs>: the tab bar
src/app/(tabs)/index.jsx first tab, Today, route "/"
src/app/(tabs)/stats.jsx second tab, Stats, route "/stats"
src/app/habit/[id].jsx opens on top of the tabs

The brackets in (tabs) make a group. The folder name does not appear in the route, so (tabs)/stats.jsx is just /stats. Every file in the folder becomes a tab, even ones you don't list.

<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432" }}>
<Tabs.Screen name="index" options={{ title: "Today" }} />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
</Tabs>

Tabs.Screen sets the order and options for one tab. name is the file name without .jsx. tabBarIcon draws the icon: a function that gets color (and focused) and returns an icon. The Expo tutorial uses Ionicons from @expo/vector-icons: <Ionicons name="today" color={color} size={24} />. Browse the names at icons.expo.fyi. Expo has said it will move to the @react-native-vector-icons packages later; the way you use an icon stays the same.

The root _layout.jsx is still a Stack, with the tabs as its first screen and their header hidden. That is why a habit's details open on top of the tab bar and Back returns to the tab you were on.

A brand new Expo project uses native tabs (NativeTabs), which draw the phone's own tab bar. You'll see them in the template. The ideas are the same; we use Tabs because the tutorial and most videos do.

People often name the file and the screen differently. stats.jsx with <Tabs.Screen name="Stats"> does not match (names are case-sensitive). Expo Router warns that no route has that name, and the tab shows without your title and icon. Use the exact file name.

When you read tabs, list the files in the (tabs) folder: that is your tab bar. Then read _layout.jsx for the order, titles and icons.

Words to recognise
Tabs(tabs)Tabs.ScreentabBarIconIonicons

A stack is for going deeper: list, then details, then edit. Tabs are for sections that are always one tap away, side by side. Think of the bar at the bottom of Facebook or bKash: Home, Search, Inbox. You don't go "back" from one to another. You just switch.

In Expo Router, tabs are a folder with a _layout.jsx that returns <Tabs>:

src/app/_layout.jsx <Stack>: the whole app
src/app/(tabs)/_layout.jsx <Tabs>: the tab bar
src/app/(tabs)/index.jsx first tab, Today, route "/"
src/app/(tabs)/stats.jsx second tab, Stats, route "/stats"
src/app/habit/[id].jsx opens on top of the tabs

The brackets in (tabs) make a group. The folder name does not appear in the route, so (tabs)/stats.jsx is just /stats. Every file in the folder becomes a tab, even ones you don't list.

<Tabs screenOptions={{ tabBarActiveTintColor: "#C6F432" }}>
<Tabs.Screen name="index" options={{ title: "Today" }} />
<Tabs.Screen name="stats" options={{ title: "Stats" }} />
</Tabs>

Tabs.Screen sets the order and options for one tab. name is the file name without .jsx. tabBarIcon draws the icon: a function that gets color (and focused) and returns an icon. The Expo tutorial uses Ionicons from @expo/vector-icons: <Ionicons name="today" color={color} size={24} />. Browse the names at icons.expo.fyi. Expo has said it will move to the @react-native-vector-icons packages later; the way you use an icon stays the same.

The root _layout.jsx is still a Stack, with the tabs as its first screen and their header hidden. That is why a habit's details open on top of the tab bar and Back returns to the tab you were on.

A brand new Expo project uses native tabs (NativeTabs), which draw the phone's own tab bar. You'll see them in the template. The ideas are the same; we use Tabs because the tutorial and most videos do.

People often name the file and the screen differently. stats.jsx with <Tabs.Screen name="Stats"> does not match (names are case-sensitive). Expo Router warns that no route has that name, and the tab shows without your title and icon. Use the exact file name.

When you read tabs, list the files in the (tabs) folder: that is your tab bar. Then read _layout.jsx for the order, titles and icons.

Words to recognise
Tabs(tabs)Tabs.ScreentabBarIconIonicons