React Native + Expo + TypeScriptで作るモバイルアプリ (Part2 - React Navigation編)
2019/11/05
Table of Contents
React Navigationの導入
基本的に公式ドキュメントのGetting started に沿っています。
Expo CLIでReact Navigationとその他必要なライブラリをインストールします。
$ expo install react-navigation react-native-gesture-handler react-native-reanimated
Navigator
React Navigationでもナビゲーション機能がついたタブ を提供していますが、今回はNativeBaseのタブをそのまま使いたいのでシンプルなSwitch Navigator を使って実現します。
そのほかにも一つ前の画面に戻ることができるStack Navigator というものもあります。
まず、ナビゲーションを実現するために、複数画面(FavoriteScreen, CameraScreen)を用意します。
お気に入り画面:
// src/FavoriteScreen/FavoriteScreen.tsx
import React from "react";
import Layout from "../Layout";
import { Text } from "react-native"
const FavoriteScreen = () => {
return (
<Layout>
<Text>Favorite</Text>
</Layout>
);
};
export default FavoriteScreen;
カメラ画面:
// src/CameraScreen/CameraScreen.tsx
import React from "react";
import Layout from "../Layout";
import { Text } from "react-native"
const CameraScreen = () => {
return (
<Layout>
<Text>Camera</Text>
</Layout>
);
};
export default CameraScreen;
これでホーム、カメラ、お気に入り画面の3画面ができました。
そして、React NavigationのcreateAppContainer(), createSwitchNavigator() を使って各画面を登録します。
import { createAppContainer, createSwitchNavigator } from "react-navigation";
import HomeScreen from "./HomeScreen/HomeScreen";
import FavoriteScreen from "./FavoriteScreen/FavoriteScreen";
import CameraScreen from "./CameraScreen/CameraScreen";
const AppNavigator = createSwitchNavigator(
{
Home: {
screen: HomeScreen
},
Favorite: {
screen: FavoriteScreen
},
Camera: {
screen: CameraScreen
}
},
{
initialRouteName: "Home"
}
);
export default createAppContainer(AppNavigator);
initialRouteName
オプションで初期表示画面を指定します。
最後にApp.tsxで呼び出します。
// App.tsx
import React from 'react';
import AppContainer from './src/AppContainer'
export default function App() {
return (
<AppContainer/>
);
}
これでReact Navigationを使った画面切り替える準備が整いました。
Hooksを使ったナビゲート
Switch Navigatorに遷移させたい画面を登録しました。
あとはNativeBaseのFooterTabコンポーネントが押されたらその画面へ遷移させる処理が必要です。
React Navigationでは NavigationContext というものがあり、Hooks APIの useContext() を一緒に拡張することで、画面遷移処理を実現できます。
// src/hooks/useNavigation.ts
import { useContext } from "react";
import {
NavigationScreenProp,
NavigationRoute,
NavigationContext
} from "react-navigation";
export function useNavigation<T>() {
return useContext(NavigationContext) as NavigationScreenProp<
NavigationRoute,
T
>;
}
NavigationScreenPropを返しています。
参考: https://github.com/react-navigation/hooks
あとは、遷移させたい箇所で useNavigation()を呼び出すだけです。
今回はフッター部分になります。
// src/Layout.tsx
import React from "react";
import {
Container,
Header,
Title,
Content,
Footer,
FooterTab,
Button,
Body,
Icon
} from "native-base";
import { useNavigation } from "./hooks/useNavigation";
interface IProps {
children: React.ReactNode;
}
const Layout = (props: IProps) => {
const navigation = useNavigation();
return (
<Container>
<Header>
<Body>
<Title>My App</Title>
</Body>
</Header>
<Content>{props.children}</Content>
<Footer>
<FooterTab>
<Button
onPress={() => {
navigation.navigate("Home");
}}
active={navigation.state.routeName === "Home"}
>
<Icon name="home" />
</Button>
<Button
onPress={() => {
navigation.navigate("Camera");
}}
active={navigation.state.routeName === "Camera"}
>
<Icon name="camera" />
</Button>
<Button
onPress={() => {
navigation.navigate("Favorite");
}}
active={navigation.state.routeName === "Favorite"}
>
<Icon name="bookmark" />
</Button>
</FooterTab>
</Footer>
</Container>
);
};
export default Layout;
これでフッターのタブをタップすると画面が切り替わると思います。
まとめ
React Navigationを導入したことで驚くほど簡単にナビゲーションを実現することができました。 Hooksをサポートしてくれてるのも嬉しいです。
次回はExpo SDKを使ってカメラなどのネイティブ機能を追加したいと思います。