React Native 入門してみた① 環境構築編+HelloWorldにつづいて今回は画面遷移についての入門です。
画面遷移
画面遷移出来ないと話にならないので学習。
候補として下記ライブラリがありましたが、GithubStar数が多く扱いやすそうなどの理由からreact-navigation
を画面遷移を実装します。
- wix/react-native-navigation: A complete native navigation solution for React Native
- aksonov/react-native-router-flux: The first declarative React Native router
- react-navigation/react-navigation: Routing and navigation for your React Native apps
構成は前回の記事同様、TypeScript構成です。
実装には、下記サイトを参考にさせて頂きました。
インストール
React Navigationをインストールします。
react-native-gesture-handler
も必要なようなので一緒にインストールします。
npm install --save react-navigation@2.0.1 react-native-gesture-handler
何故@2.0.1
なのかは下記、問題1. ビルドエラーを参考下さい。
実装
構造
├── App.tsx
├── app.json
├── assets
│ ├── icon.png
│ └── splash.png
├── babel.config.js
├── package-lock.json
├── package.json
├── src
│ ├── navigator
│ │ └── index.ts
│ └── screens
│ ├── Main.tsx
│ ├── Modal.tsx
│ └── Push.tsx
└── tsconfig.json
src/navigator/index.ts
に画面の遷移処理を記載します。
screens/
配下のコンポーネントが各画面です。
ナビゲーションの実装
navigator/index.ts
import { createStackNavigator, NavigationScreenProp } from 'react-navigation'
//画面
import Main from '../screens/Main'
import Push from '../screens/Push'
import Modal from '../screens/Modal'
export interface HomeScreenProps {
navigation: NavigationScreenProp<any, any>
};
export const MainNavigation = createStackNavigator(
{
Main: { screen: Main },
Push: { screen: Push },
},
{ initialRouteName: 'Main', mode: 'card', headerMode: 'none' }
)
export default createStackNavigator(
{
MainNavigation: { screen: MainNavigation },
Modal: { screen: Modal },
},
{ initialRouteName: 'MainNavigation', mode: 'modal', headerMode: 'none' },
)
ここでは各画面の遷移処理を記載します。
画面はscreens/
配下に作成します。
createStacknavigator
を使用して画面遷移を作成します。
initialRouteName
で初期画面を設定し、画面遷移の方法はmode
を指定して変更します。
modeはレンダリングと遷移のスタイルを定義します。
modal
・card
の種類が存在しそれぞれ下記になります。
- modal: 標準のiOSとAndroidの画面遷移を使用します。 これがデフォルトです。
- card: 画面を下からスライドさせます。iOSでのみ動作し、Androidでは動作しません。
続いて、各画面の実装します
screens/Main.tsx
import React, {Component} from 'react';
import { Container, View, Header, Left, Body, Right, Button, Title, Text } from 'native-base';
import {HomeScreenProps} from '../navigator'
export default class Main extends Component<HomeScreenProps> {
push = () => {
const { navigation } = this.props
navigation.navigate('Push')
}
modal = () => {
const { navigation } = this.props
navigation.navigate('Modal')
}
render() {
return (
<Container>
<Header>
<Left />
<Body>
<Title>メイン</Title>
</Body>
<Right />
</Header>
<View>
<Button small iconRight transparent primary onPress={this.push}>
<Text>プッシュ表示</Text>
</Button>
</View>
<View>
<Button small iconRight transparent primary onPress={this.modal}>
<Text>モーダル表示</Text>
</Button>
</View>
</Container>
);
}
}
メイン画面の実装です。
this.props.navigation.navigate
を使用することで画面遷移出来ます。
.navigate('Push')
でPush画面に遷移、PushをModalとすることで、Modal画面に遷移出来ます。
screens/PUsh.tsx
import React, {Component} from 'react';
import { Container, Header, Left, Body, Right, Button, Icon, Title } from 'native-base';
import {HomeScreenProps} from '../navigator'
export default class Push extends Component<HomeScreenProps> {
render() {
return (
<Container>
<Header>
<Left>
<Button transparent onPress={() => this.props.navigation.goBack()}>
<Icon name='arrow-back' />
</Button>
</Left>
<Body>
<Title>プッシュ</Title>
</Body>
<Right />
</Header>
</Container>
);
}
}
this.props.navigation.goBack()
で前の画面に戻ることが出来ます。
App.tsx
import React, { Component } from 'react';
import Navigator from './src/navigator';
export default class App extends Component {
render() {
return (
<Navigator />
);
}
}
ルート(親)コンポーネントでは、<Navigaror/> (src/navigator/index.ts)
コンポーネントをrenderします。
ハマったポイント
実装中にハマったポイントです。
問題1. ビルドエラー
Tried to register two views with the same name RNGestureHandlerButton
register
ReactNativeViewConfigRegistry.js:76:4
-
Tried to register two views with the same name RNGestureHandlerButton – React Native Navigation – Knoll Labs
上記によるとVerseion3系で発生するようで2にダウングレードすると問題なく動きます
"react-navigation": "^2.0.1"
問題2. TypeScript対応時の各ページのPropsについて
type Props = {}
export default class Main extends Component<Props> {
...
として場合、 this.props.navigation.navigate('Push')
でエラーとなってします。
そこで、react-navigationからinterfaceを作成する
import { createStackNavigator,NavigationScreenProp} from 'react-navigation'
export interface HomeScreenProps {
navigation: NavigationScreenProp<any,any>
}
上記interfaceを各画面のPropsに追加することで対応できます
typescript - Add strong typing for react navigation props - Stack Overflow
Next
続いては、React Native 入門してみた③ Httpアクセスです。