【React Native】Expo Routerを導入する
概要
今回は、React Native に Expo Router を導入して基本的なルーティングを構築して動作確認しました。あわせて BottomTab ナビゲーションと併用する方法も検証してみました。
Expo Router とは?
React NativeとWebアプリケーションのためのファイルベースのルーティングライブラリ
Next.js みたいな使い方ができる様です 👀
動作環境構築
早速試していく環境を作成します。 react-native-example
ディレクトリを作成し blank-typescript
のテンプレートを用いてプロジェクトを作成します。
$ mkdir react-native-example
$ cd react-native-example
$ npx create-expo-app@latest --template blank-typescript
この時点での package.json
の dependencies
は以下になりました。
"dependencies": {
"expo": "~52.0.41",
"expo-status-bar": "~2.0.1",
"react": "18.3.1",
"react-native": "0.76.7"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~18.3.12",
"typescript": "^5.3.3"
},
インストール
👆のドキュメントの Manual installation
前提で進めていきます。
npx expo install expo-router react-native-safe-area-context react-native-screens expo-linking expo-constants
複数パッケージを一気にインストールするみたいなので、1個ずつ調べてみたいと思います。
- expo-router
- 今回試すパッケージ
-
react-native-safe-area-context
- デバイスのSafe Area Inset にアクセスするための柔軟なAPIを提供
- ノッチ、ステータスバー、ホームインジケータ、その他のデバイスやオペレーティングシステムのインターフェイス要素の周囲にコンテンツを適切に配置することができる
- SafeAreaView コンポーネントも提供しており、View の代わりに使用することで、セーフエリアを考慮したビューを自動的に挿入することができる
-
react-native-screens
- 通常 ReactNative の画面遷移は JavaScript 上で管理されるが、
react-native-screens
を導入することで、iOS のUINavigationController
や Android のFragment
など、各プラットフォームのネイティブな画面管理を利用できる - これにより、画面遷移がよりスムーズになり、メモリ使用量も最適化される
- 通常 ReactNative の画面遷移は JavaScript 上で管理されるが、
-
expo-linking
- ディープリンクを簡単に扱える様にする
-
expo-constants
- アプリに関するさまざまな定数情報(アプリ名、バージョン、ビルド番号、デバイス情報など)を取得できる
👆でインストールされたパッケージは以下になります。
"dependencies": {
...
"expo-router": "~4.0.20",
"react-native-safe-area-context": "4.12.0",
"react-native-screens": "~4.4.0",
"expo-constants": "~17.0.8",
"expo-linking": "~7.0.5"
},
次に package.json
の main
を以下に変更します。
{
"main": "expo-router/entry"
}
次に app.json
または app.config.js
に以下を追加します。
{
"expo": {
"scheme": "your-app-scheme",
"plugins": ["expo-router"]
}
}
これで準備完了です。
ルートページ表示
ちゃんと設定できているか、ルートページだけ設定して表示させてみたいと思います。
まず既存の App.tsx
を削除し、新たに app
ディレクトリを作成し中に index.tsx
を以下内容で作成します。
import { Text } from 'react-native';
const Page = () => {
return <Text>Page</Text>;
};
export default Page;
これで npm run start
でアプリを起動し Page
が表示されとけばOKです。
BottomTab と併用する
最後に Bottom Tabs を使う場合はどうなるのか試してみたいと思います。
以下公式ドキュメントを参考に進めていきたいと思います。
まずは app/_layout.tsx
を以下内容で作成します。
import { Stack } from 'expo-router/stack';
const Layout = () => {
return (
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
</Stack>
);
};
export default Layout;
Stack の Stack.Screen
を用いて起動されたら子ルート (tabs)
をStackに追加し、 (tabs)
配下が表示されます。StackはAndroid では FragmentActivity
+Fragment
、iOS では UINavigationController
+UIViewController
に置き換わる様です。
次に (tabs)
ディレクトリを作成し app/(tabs)/_layout.tsx
を以下内容で作成します。
import FontAwesome from '@expo/vector-icons/FontAwesome';
import { Tabs } from 'expo-router';
const 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>
);
};
export default TabLayout;
最後に各タブの中身を実装していきます。 app/(tabs)/index.tsx
と app/(tabs)/settings.tsx
を以下内容で作成します。
import { StyleSheet, Text, View } from 'react-native';
const Tab = () => {
return (
<View style={styles.container}>
{/* index.tsxの場合はHome, settings.tsxはSettingsにする*/}
<Text>Tab [Settings or Home]</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
export default Tab;
早速動かしてみると👇の様になります。うまく動いてそうです ✨
ちなみに app/_layout.tsx
の options={{ headerShown: false }}
を true
にすると ネイティブのナビゲーションバーが表示されてしまいます 👇。今回はtabが用意しているヘッダーを使うので非表示に設定しています。
参考URL
Discussion