スタックナビゲーション
モバイルアプリで最も一般的なナビゲーションパターンのひとつが「スタックナビゲーション」です。これは、新しい画面が前の画面の上に積み重なるように表示され、ユーザーは「戻る」操作で前の画面に戻ることができる、というものです。
例えば、商品一覧画面から商品詳細画面へ遷移し、さらにレビュー投稿画面へ進む、といった一連の流れを想像すると分かりやすいでしょう。多くのOSで標準的な「戻る」ボタン(ヘッダーの左矢印や、Androidの物理/ジェスチャーバックボタン)がこのスタックの操作と連動します(図4)。

Expo Routerでは、このスタックナビゲーションを簡単に実装するための仕組みが提供されています。expo-router
パッケージに含まれるStack
コンポーネントをレイアウトルート (_layout.js
) で使用します。
基本的なスタックナビゲーションの設定
特定の画面群(例えば設定関連の画面すべて)にスタックナビゲーションを適用したい場合、それらの画面ファイルを一つのディレクトリにまとめ、そのディレクトリ直下にレイアウトルートファイル (_layout.js
) を作成します。そして、この_layout.js
からStack
コンポーネントをエクスポートします。
例として、app/settings/
ディレクトリ内に設定関連の画面 (index.js
, profile.js
, notifications.js
) を配置し、これらをスタックナビゲーションで管理するケースを考えます。ファイル構成はリスト3のようになります。
app/ ├── settings/ │ ├── _layout.js // settingsディレクトリ用スタックナビゲーションのレイアウト │ ├── index.js // /settings (設定トップ画面) │ ├── profile.js // /settings/profile (プロフィール編集画面) │ └── notifications.js // /settings/notifications (通知設定画面) └── _layout.js // アプリ全体のルートレイアウト
図4のようなイメージの画面遷移ができるとよいですね。

これを実現するには、app/settings/_layout.js
の内容はリスト4のようになります。
// app/settings/_layout.js import { Stack } from 'expo-router'; export default function SettingsStackLayout() { return ( <Stack> {/* (1) 各画面のヘッダー設定などをここで行う */} <Stack.Screen name="index" options={{ title: '設定' }} /> <Stack.Screen name="profile" options={{ title: 'プロフィール編集' }} /> <Stack.Screen name="notifications" options={{ title: '通知設定' }} /> </Stack> ); }
このapp/settings/_layout.js
が、settings
ディレクトリ内のすべての画面ファイル (index.js
, profile.js
, notifications.js
) に対する共通レイアウトとして機能します。Stack
コンポーネントを返すことで、これらの画面がスタックとして管理されるようになります。
(1)のようにStack
コンポーネントの子要素として<Stack.Screen name="ファイル名" options={{...}} />
を記述することで、各画面がスタックに登録され、ヘッダーのタイトル ( options={{ title: '...' }}
) などのナビゲーションオプションを指定できます。
name
属性には、settings
ディレクトリ内のファイル名(拡張子なし)を指定します。例えばindex.js
ならindex
、profile.js
ならprofile
です。
これにより、/settings
(settings/index.js) から/settings/profile
(settings/profile.js) へLink
コンポーネントで遷移すると、profile.js
の画面がindex.js
の画面の上に重なって表示され、ヘッダーには自動的に「戻る」ボタンと「プロフィール編集」というタイトルが表示されます(図6)。

スタックナビゲーションを利用することで、進んだり戻ったりする基本的な画面遷移を簡便に実装できますね。
タブナビゲーション
スタックナビゲーションと並んで、モバイルアプリで頻繁に用いられるのが「タブナビゲーション」です。
これは通常、画面の下部(時には上部)に複数のタブが配置され、各タブをタップすることで対応する画面に切り替わるというインターフェースです。アプリの主要な機能セクションへのショートカットとして機能し、ユーザーは少ない操作で目的の画面に素早くアクセスできます(図7)。

Expo Routerでは、このタブナビゲーションもexpo-router
パッケージに含まれるTabs
コンポーネントをレイアウトルート (_layout.js
) で使用することで簡単に実装できます。
基本的なタブナビゲーションの設定
タブナビゲーションをアプリの主要な画面群(例:ホーム、検索、マイページなど)に適用するには、これらの画面をグループルートでまとめ、そのグループのレイアウトルート (app/(tabs)/_layout.js
など) で Tabs
コンポーネントをデフォルトエクスポートします。
例えば、ホーム画面 (home.js
)、検索画面 (search.js
)、マイページ画面 (mypage.js
) をタブで切り替えられるようにしたい場合、リスト5のようなファイル構成になります。
app/ ├── (tabs)/ │ ├── _layout.js // タブナビゲーションのレイアウト定義 │ ├── home.js // /home (ホーム画面) │ ├── search.js // /search (検索画面) │ └── mypage.js // /mypage (マイページ画面) └── _layout.js // アプリ全体のルートレイアウト
これらのファイルをタブナビゲーションで扱うには、リスト6のように登録します。
// app/(tabs)/_layout.js import { Tabs } from 'expo-router'; import { FontAwesome } from '@expo/vector-icons'; // アイコン表示のため export default function TabLayout() { return ( <Tabs screenOptions={{ // (6) // tabBarActiveTintColor: 'blue', // アクティブなタブの色などを指定できる }} > <Tabs.Screen name="home" // (1) options={{ // (2) title: 'ホーム', // (3) tabBarIcon: ({ color, size }) => ( // (4) <FontAwesome name="home" size={size} color={color} /> ), }} /> <Tabs.Screen name="search" options={{ title: '検索', tabBarIcon: ({ color, size }) => ( <FontAwesome name="search" size={size} color={color} /> ), }} /> <Tabs.Screen name="mypage" options={{ title: 'マイページ', tabBarIcon: ({ color, size }) => ( <FontAwesome name="user" size={size} color={color} /> ), // (5) headerShown: false, // ヘッダーを非表示にする場合 }} /> </Tabs> ); }
この(tabs)/_layout.js
が、(tabs)
ディレクトリ内のすべての画面 (home.js
, search.js
, mypage.js
) に対するレイアウトとして機能し、Tabs
コンポーネントを返すことで、これらの画面がタブインターフェースで管理されるようになります。Tabs
コンポーネントの直下には<Tabs.Screen ... />
を配置し、各タブに対応する画面を指定します。
(1)のname
属性には、グループルート内のファイル名(拡張子なし)を指定します。(2)の options
属性では、各タブの見た目や挙動をカスタマイズします。(3)のtitle
プロパティはタブのラベルや、そのタブが選択されている時のヘッダータイトルとして使用されます。(4)のtabBarIcon
は、タブに表示されるアイコンを指定する関数です。引数としてcolor
と size
を受け取り、アイコンコンポーネントを返します。上記の例では@expo/vector-icons
のFontAwesome
を使用しています。(5)のheaderShown: false
を指定すると、そのタブがアクティブな時にデフォルトで表示されるヘッダーを非表示にできます(図8)。

Tabs
コンポーネント自体の設定である(6)のscreenOptions
プロパティでは、すべてのタブに共通のオプション(例:アクティブなタブのアイコンやラベルの色tabBarActiveTintColor
)を指定することも可能です。