ReactでFirebase HostingとFirestore


巷でFirebaseが流行ってるようなのでReactアプリFirebaseを使う方法をまとめました。15分もあればFirestoreを使うReactアプリをFirebase Hostingをデプロイできるでしょう。

Firebaseにはたくさんの機能がありますが、次の二つを使います。

- Firebase Hosting: SPAなど静的ファイルをデプロイできるサービス
  - Reactアプリをデプロイする先です。
- Firebase Cloud Firestore: ドキュメントDBのサービス
  - Reactアプリから呼び出します。

## Firebaseのプロジェクト作成

まずは、[Firebase](https://firebase.google.com)のWebサイトでプロジェクトを作ります。

1. Firebaseにサインアップします。Googleアカウントがあればすぐ登録できます。
2. プロジェクトを新規作成します。

## Firebase CLIのセットアップ

SPAをFirebase HostingにデプロイするためにCLIをインストールします。

1. CLIをインストールします。

```
npm install -g firebase-tools
```

2. CLIでFirebaseへログインします。

```
firebase login
```

ブラウザが立ち上がってログイン画面が表示されるのでログインします。

## Reactアプリの作成

Reactアプリを作ってビルドします。今回はReactとFluxのスターターキット[starter-react-flux](https://github.com/SokichiFujita/starter-react-flux)を使います。

```
mkdir myapp && cd myapp
npx starter-react-flux init
npm run build
```

さて、これでReactアプリのビルドまで終わりました。

次はFirebase Hostingへのデプロイです。

## Fireabase Hostingへのデプロイ

1. Firebaseの初期設定を行います。

```
firebase init
```

色々聞かれるので次のように選択します。

- Which Firebase CLI features do you want to setup for this folder
  - `Hosting: Configure and deploy Firebase Hosting sites`をスペースキーで選択してリターン
- Select a default Firebase project for this directory
  - webで作成しておいたprojectを選択
- What do you want to use as your public directory?   
  - `public` (何も入力せずリターン)
- Configure as a single-page app (rewrite all urls to /index.html)
  - `Y`
- File public/index.html already exists. Overwrite
  - `n`

2. ReactアプリをFirebase Hostingにデプロイします。

デプロイは1コマンド打つだけです。

```
firebase deploy
```

3. 動作確認

デプロイ後に表示される`Hosting URL`をブラウザで開くとReactアプリが確認できます。

```
=== Deploying to '*****'...
略
✔  Deploy complete!
Project Console: https://console.firebase.google.com/project/*****/overview
Hosting URL: https://*****.firebaseapp.com
```

## Firestoreのデータベース作成

さてこれからはFirestoreを作ってReactアプリから使ってみます。

1. WebのコンソールからCloud Firestoreを選択します。
  - Cloud FirestoreとRealtime Databaseがありますが、Cloud Firestoreを使います。
2. Cloud FirestoreにDBを作成します。
  - テストモードを選択します。
3. 「コレクションを追加」をクリックして、作成したDBにcollectionを作成します。
  - コレクション名: `articles`
ß4. 「ドキュメントを追加」をクリックして、collectionに適当なdocumentをひとつ作成します。
  - `title` (string): 任意の文字列
  - `subtitle` (string): 任意の文字列
  - `text` (string): 任意の文字列

## ReactアプリからFirestoreへの接続

Firestoreからデータを呼び出して表示するだけのシンプルなアプリを作ります。

1. ReactアプリにfirebaseのSDKを追加します。

```
npm install --save firebase
```

GitHub: [firebase/firebase-js-sdk](https://github.com/firebase/firebase-js-sdk)

2. FluxのAction CreatorからCloud Firestoreにアクセスします。

	`app/actions/SampleActionCreators.js` を開いて、以下を追加します。


```js
import firebase from 'firebase/app'; //必須
import 'firebase/firestore'; //必要なモジュールごとにimport
//例: Cloud Functionを使う場合は import 'firebase/function';

//インスタンスの初期化
firebase.initializeApp({
  apiKey: '*****',
  authDomain: '*****',
  projectId: '*****'
});

const db = firebase.firestore();
```

※ API keyなどの入力項目はWebコンソールの「プロジェクトの設定」>「アプリ」>「ウェブアプリに Firebase を追加」に記載されています。
※ 認証情報はコードに直書きせず環境変数で指定してビルドするのがThe Twelve-Factor App的にはいいですが今回は割愛します。

初めからあるサンプルのAction Creator( `actionCreator001()` )を次のように変更します。

```js
  actionCreator001() {
    //articlesコレクションから1件データを取得
    db.collection("articles").limit(1).get().then((response) => {
      //forEach()でドキュメントの配列がとれる
      response.forEach((doc) => {
        //data()でドキュメントがとれる
        const document = doc.data();
        //dispatch()でFluxのストアに送信
        AppDispatcher.dispatch({
          type: ActionTypes.TYPE_001,
          data: {
            "title": document.title,
            "subtitle": document.subtitle,
            "text": document.text
          },
        });
      });
    });
  },
```

3. ビルド & デプロイ

アプリをビルドしなおして、Firebase Hostingに再度デプロイします。

```
npm run build
firebase deploy
```

4. 動作確認

ボタンをクリックするとFirestoreから取得したデータが表示されます。

## まとめ

- Firebase Hostingには`firebase deploy`だけでReactのSPAをデプロイできる。
- Firebase Cloud FirestoreはAction Creatorから簡単に呼べる。

SNS認証をつける方法は[こちら](https://qiita.com/sl2/items/2815e62aaf2baea2f589)

- [Firebase AuthenticationでReactアプリにTwitter/Facebook/Google認証をつける](https://qiita.com/sl2/items/2815e62aaf2baea2f589)