React Native体験入学【環境構築】【標準コンポーネントの使い方】【リリースまで】

最近までNext.jsの入門してブログシステム作ってたけど、どうもwebpack周りで詰んでしまったのでもう少し実戦練習できることをやってみようと思ってReact Nativeを始めることに。あまりNext.jsに向いてないブログシステム作るより、ガッツリReact使いまくるアプリ制作でコーディングしまくりたい。

とりあえずReact Nativeの基本情報と、環境構築、ドキュメントやリファレンスの流し読み、そして簡単なアプリを作ってみようと思う。予定は簡単な「ダイス」アプリ。できればリリースするところまで経験しておきたい。

##目次（暫定）

1. **環境構築**
    1. React Nativeとは（クロスプラットフォーム開発環境）
    1. Reactとは（UI構築のためのJSライブラリ）
    1. Expoとは（OSに依存しないビルド環境）
    1. 統合開発環境
        2. Xcode
        3. Android Studio
    1. 開発ツールのインストール
        2. Homebrew
        3. Node.js
        4. Watchman
        5. react-native-cli
    1. 動作テスト
1. **仕様**
    1. 標準コンポーンネント
    1. 標準API
    2. StyleSheet
    3. HTTP通信
    4. アニメーション
    5. データの保持
    6. 画面遷移（navigation・pagenation）
    7. 標準UI（React Native Elements）
8. **ビルド・リリース**
    9. Google Play
    10. AppStore 
    11. デバッグとアップデート

## React Nativeとは

- Facebookが開発したクロスプラットフォーム開発フレームワーク
- FlutterみたいなやつのReact版
- 同じコードでWeb・iOS・Androidアプリが作れる
- OSのAPIの仕様の差をフレームワークレベルで抽象化することで共通化
- JavaScriptとReactの知識があればモバイルアプリを作れる

##Reactとは

UI構築のためのJSライブラリ。コンポーネントは状態を持ったviewの単位。Reactではコンポーネントを組み合わせてUIを構築する。その辺はReact.jsの方の公式ドキュメントなどで勉強すべし。

###コンポーネントライフサイクル

これはいずれ理解しないといけないややこしい部分。数が多いのでまた今度気合入れて勉強しとく。

- `ReactDOM.render`
- `constructor()`
- `getInitialState()`　非推奨。constructor()推奨。
- `componentDidMount()`
- `componentWillUnmount()`
- `shouldComponentUpdate()`
- `getSnapshotBeforeUpdate()`
- `componentDidUpdate()`
- `componentDidCatch()`

##Expoとは

- OSに依存しないビルド環境
- スマホ用の開発環境アプリがある
- 同じネットワークなら無線接続でテスト可能
- 利用には会員登録が必要

###Expo Snack

ブラウザ上でコードの動作をリアルタイムで確認できるツール。ReactのCodePenやCodeSandboxのようなもの。

###アプリの実行方法は2つ

実機で動かすのと、シミュレータで動かすもの。

実機で動かすときは、Expo.ioからプロジェクトを開始したら表示されるQRコードを、スマホのExpoアプリで読み取れば起動する。

シミュレータで動かすときは、`expo-cli`というコマンドラインツールをPCにnpmインストールして、`expo init`コマンドを実行することでExpoプロジェクトに接続可能。ただし`react-native init`コマンドとは異なることに注意。

コマンドラインからでも`expo start`コマンドでQRコードから実機接続できる。また、このときに`i`を入力すればシミュレータが起動する。

##統合開発環境

実機を持ってなくとも新旧機種を問わず動作テストできる環境を構築する。それにはXcodeとAndroid Studioといった統合開発環境をインストールすればいい。ただしiOSアプリの開発はMacOSでしかできない。以下、必要なツールをリストアップしておく。

**Xcode**

**Android Studio**

- Java（開発言語）
- JDK（Java開発キット）
- SDK（ソフトウェア開発キット）
- AVD（Android仮想デバイス）

**その他**

- Homebrew（パッケージマネージャ）
- Node.js（非同期のJSライブラリ）
- Watchman（ファイルシステムの監視ツール）
- react-native-cli（コマンドラインツール）
- Expo

##動作テスト

[公式ドキュメント](https://facebook.github.io/react-native/docs/getting-started)を参考に一通りやってみる。

###各種インストール

環境はMacOS & iOSを選択。そしてXcodeをインストールすることでHomebrewが使えるようになる。

```zsh
$ brew install node
$ brew install watchman
$ sudo gem install cocoapods
```

```zsh
$ npx react-native init MyTestApp
```

```zsh
$ npm install -g react-native-cli
$ react-native init MyTestApp
```

###シミュレータ起動して試運転

アプリをシミュレータで起動するコマンド。

```zsh
$ cd MyTestApp
$ npx react-native run-ios
```

<img width="364" alt="スクリーンショット 2020-01-19 20.51.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/b9372b7b-d876-7b5a-4759-7cc59cfba00a.png">

`App.js`を編集して保存したらホットリロードされる。

<img width="364" alt="スクリーンショット 2020-01-19 20.52.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/79a7e591-1c4d-067c-4396-8467e3afbaa7.png">

次に[公式ドキュメント](https://facebook.github.io/react-native/docs/tutorial)のHello Worldコードを`App.js`にコピペして保存してみる。ここからは普通のReactのコーディングだと思えばわかりやすい。

```App.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';    // react-native標準コンポーネントのインポート

export default class HelloWorldApp extends Component {
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text>Hello, world!</Text>
      </View>
    );
  }
}
```

<img width="364" alt="スクリーンショット 2020-01-19 20.52.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/840430a8-a6c6-3515-0829-74f2b5794769.png">

ちょっとだけ自由に編集してみた。まずrootディレクトリに`public/`を作成し、`profile.png`を配置。そして`App.js`で`Image`コンポーネントをインポートのところに追加し、`render()`の中にpropsやstyleを与えた`<Image />`を記述。ついでに`<Text>`のフォントサイズのstyle追加とテキストを変更してみた。レイアウトは`<View>`コンポーネントのstyleでセンタリングされて表示される。

```jsx
import React, { Component } from 'react';
import { Text, View, Image } from 'react-native';

export default class HelloWorldApp extends Component {
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text style={{fontSize:30}}>お絵描きホーホー論</Text>
        <Image style={{width: 100, height: 100}} source={require('./public/profile.png')} />
      </View>
    );
  }
}
```

<img width="364" alt="スクリーンショット 2020-01-20 1.36.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/d9476629-aaee-042c-ed0b-961c03ee27ae.png">

##標準コンポーネント

React Nativeのコンポーネントの構造についてサッと頭に入れておくと知識を蓄積しやすくなるかも。下図は公式サイトのトップページにある図解。React Nativeではいくつかの標準コンポーネントを提供しており、それをツリー構造で配置することでUIを構築し、そのReactコンポーネントはネイティブなコードをラップしているため、ネイティブコードを一切触らずにJavaScriptでのアプリ開発ができる、という触れ込みが書かれている。

<img width="463" alt="スクリーンショット 2020-01-19 23.21.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/4627f237-caf6-f227-a6eb-3efadbe916b7.png">

<img width="370" alt="スクリーンショット 2020-01-19 23.22.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278293/7668a114-ab94-0147-7221-ed2559f34ea6.png">


標準コンポーネントの種類については、[公式ドキュメント](https://facebook.github.io/react-native/docs/components-and-apis)のコンポーネントとAPIのリファレンスを参考。基本的な説明と、渡せるpropsの一覧が見れる。名称から用途が想像できるものもあるが、各プラットフォーム専用のコンポーネントもあるので要勉強（下記が全てではない）。

- 基本コンポーネント
    - View
    - Text
    - Image
    - TextInput
    - ScrollView
    - StyleSheet
- UI
    - Button
    - Picker
    - Slider
    - Switch
- List Views
- iOS Components and APIs
- Android Components and APIs
- Others
    - Activity Indicator
    - Alert


###Viewコンポーネント

HTMLでいう`<div>`のような役割。要素を入れるコンテナとして、レイアウトを作るのに使える。

```jsx
return(
  <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
    （中略）
  </View>
);
```

###Textコンポーネント

テキスト表示用で、HTMLと違ってReact Nativeではこのコンポーネントを使わないとテキスト表示ができない。

```jsx
return(
  <Text>Hello World</Text>
);
```

###Imageコンポーネント

画像を表示する。画像ファイルパスは`require`で`public/`などの静的ファイル用のディレクトリを参照するようになる。Imageコンポーネントは`style`でサイズ指定しなけれな表示されない。基本的には位置調整のため`<View>`コンポーネントに入れて配置する。

```jsx
return(
  <Image style={{width: 100, height: 100}} source={require('./assets/sample.png')} />
  <Image style={{width: 100, height: 100}} source={{uri: 'https://facebook.github.io/reactnative/img/favicon.png'}} />
);
```

##Native Baseの導入してUI構築

Native BaseはReact NativeにUIコンポーネントを追加するライブラリ。そもそもReact Nativeはクロスプラットフォーム開発環境を提供することに重点を置いているので、OSごとに仕様が異なるUI設計などについては最低限のサポートしかしてくれない。例えば`<Button>`の標準コンポーネントだけだとiOSではボタンではなくただのテキストとしてしか表示されない。

npmでインストールしてから`link`を実行することで有効にする。

```zsh
$ npm i -S native-base
$ react-native link
```

使い方は`react-native`の代わりに`native-base`としてコンポーネントをインポートすればいい。

```App.jsx
import React, { Component } from 'react';
import { Container, Button, Text } from 'native-base';
export default class GeneralExample extends Component {
  render() {
    return (
      <Container>
        <Button>
          <Text>
            Button
          </Text>
        </Button>
      </Container>
    );
  }
}
```

##UIライブラリ

[React Native Basic Components](https://facebook.github.io/react-native/docs/view)
[React Native Elements](https://react-native-elements.github.io/react-native-elements/)
[Native Base](https://nativebase.io/)
[IonIcons](https://ionicons.com/)

##エラー対応

[npmでpermission deniedになった時の対処法[mac]](https://qiita.com/okohs/items/ced3c3de30af1035242d)