ReactにFirebaseを使ったログイン機能を実装する

## この記事の内容を一言で
**自作の[家計簿アプリ](https://myself-calculator.herokuapp.com/)にFirebaseを用いてログイン機能を作成する**

## 問題
家計簿アプリにログイン機能を実装して、ユーザー別に各項目を保存できるようにしたい

## 解決策
Firebaseを使用する

## 解決法
### Firebaseについて
FirebaseはGoogleが提供しているサービスの一つ。
Baas(Backend as a service)/mBaas(mobaile Backend as a service)を提供している。
Firebaseを利用することで、フロントエンドの開発者でも簡単にデータベースが必要な作業をシステムに実装することができるように。
データベースに関する知識も必要だけど、今求めていることはそこではないため、今回はFirebaseを用いて問題を解決する。

Firebaseについて: [Firebaseの始め方](https://qiita.com/kohashi/items/43ea22f61ade45972881)
Baasについて: [BaaSからSaaSまで！いま一度、クラウドサービスの違いを整理しよう](https://blog.mbaas.nifcloud.com/entry/diffirentofbaasandsaas)

#### Firebaseのドキュメント
[Firebase を JavaScript プロジェクトに追加する](https://firebase.google.com/docs/web/setup?authuser=0)
[Firebase Authentication](https://firebase.google.com/docs/auth/?authuser=0)

### Firebaseの導入
まずはPCにFirebaseを導入する。

```install.sh
 $ npm install firebase
```

#### メモ
`npm.sh`を実行した際、以下のエラーが発生した。
<img src="https://qiita-image-store.s3.amazonaws.com/0/218398/cc4bc9fc-4866-b111-081c-be8559a0e260.png" width="500px">
` $ npm audit fix`を使うことで治せるとあるが、詳細を確認するため`$ npm audit`を打つ。
<img src="https://qiita-image-store.s3.amazonaws.com/0/218398/89bc5528-0f75-82c4-78d0-2f4ec0da1bd8.png" width="500px">

セキュリティの問題らしい。
今のバージョンだとセキュリティ上良くないんで、更新してほしいと。
`More info`にあるhttps://www.npmjs.com/advisories/725 をみると、バージョンを更新することで解決できると書いてあるので、更新する。
実行したのは以下のコマンド。

```yarn.sh
 $ yarn add react-scripts@2.1.3
```
このあとに、yarn版のFirebaseをインストールするコマンドを実行したら無事解決。

```yarn_install.sh
 $ yarn add firebase
```

### ログイン機能の実装
次に、ログイン機能を実装していく。
[Firebase](https://firebase.google.com/?hl=ja)にログインして、アプリの名前などを決める。
それが終わったら、この画面からコードをコピーする。
`</>`のボタンを押すとコードが表示される。
<img src="https://qiita-image-store.s3.amazonaws.com/0/218398/265c4be5-49c1-decd-c6bb-95c51aabaec6.png" width="500px">

コードをコピーしたら、firebase用のディレクトリを作成し、コピーしたコードをペーストするファイルを作成する。

```copy.sh
 $ mkdir firebase
 $ vim firebase.js
```

```firebase.js
import firebase from 'firebase/app'
import 'firebase/auth'

const config = {
   apiKey: "***",
   authDomain: "***",
   databaseURL: "***",
   projectId: "***",
   storageBucket: "***",
   messagingSenderId: "***"
}
// "***"の部分にコピーしたコードの内容をペーストする。

firebase.initializeApp(config);

export default firebase
```

続いて、ログイン、ログアウトのボタンを作成していく。

```Auth.sh
 $ mkdir Auth
 $ vim Auth.js
```

```Auth.js
import React, { Component } from 'react'
import firebase from './firebase'

class Auth extends Component {
  state = {
    user: null
  }

  componentDidMount() {
    firebase.auth().onAuthStateChanged(user => {
      this.setState({ user })
    })
  }
  //componentDidMountはrenderが実行された後に行われる。データの受け渡しが可能な状態になったら下記のコードが実行されていく。
  //onAuthstateChangeでuserにログインしたユーザーの情報を与える
  
 login() {
    const provider = new firebase.auth.GoogleAuthProvider()
    firebase.auth().signInWithRedirect(provider)
  }
  //signInWithRedirectでGoogleのログインページに接続して、Google プロバイダ オブジェクトのインスタンスを作成する。
  logout() {
    firebase.auth().signOut()
  }

  render() {
    return (
      <div className="Auth">
        {this.state.user ? (
           <h1 className="UserName">{this.state.user && this.state.user.displayName}の家計簿</h1>
           // displayNameでログインした人のGoogleアカウントに登録されている名前を表示する
        ) : (
           <h1 className="Name">あなたの家計簿</h1>
　　　　　　//ログインしていない人用の表示
        )}
        {this.state.user ? (
          <button onClick={this.logout}>Google Logout</button>
　　　　　　//ユーザーがログインしている時はlogoutボタンを表示する
        ) : (
          <button onClick={this.login}>Google Login</button>
　　　　　　//ユーザーがいない時はloginボタンを表示する
        )}
      </div>
    )
  }
}

export default Auth
```
こちらのコードのほとんどは[10分でできるReact+FirebaseのGoogleAuth](https://qiita.com/HorieH/items/8b4b1c4807e1eb6fcb0a)から。
自分なりに解釈したものをコメントアウトに記述。

あとは、`Auth.js`で作成したコンポーネントを`app.js`に設置し、各自の環境でサーバーを起動して、Firebaseが導入、実行されているかを確認する。

`componentDidMount`について: [5分で理解する React.js](https://qiita.com/tomzoh/items/7fabe7cb57dd96425867#componentdidmount)
`GoogleAuthProvider`について: [Google ログインと JavaScript を使用して認証する](https://firebase.google.com/docs/auth/web/google-signin?hl=ja)
`displayName`について: [Firebase でユーザーを管理する](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)

### コードを隠す
`firebase.js`のコードをGithubなどのインターネットに挙げるときはAPIキーを隠す。
その方法は、`package.json`といった、プロジェクトのroot階層に`.env`ファイルを作成することでできる。
また、`create-react-app`を使っている場合、`.env`に書くのは`REACT_APP〜`である必要があった。
今回は`apiKey`と`messagingSenderId`を隠してみる。


```.env
 REACT_APP_FIREBASE_APIKEY="***"
 REACT_APP_FIREBASE_MESSAGING_SENDER_ID="***"
```

```firebase.js
import firebase from 'firebase/app'
import 'firebase/auth'

const config = {
   apiKey: process.env.FIREBASE_APIKEY,
   authDomain: "***",
   databaseURL: "***",
   projectId: "***",
   storageBucket: "***",
   messagingSenderId: FIREBASE_MESSAGING_SENDER_ID
}

firebase.initializeApp(config);

export default firebase
```

という風に。
エラーが発生しても、`yarn start`をすることで認識される場合があるため、確認する。

`.env`の読み込みについて: [create-react-appのプロジェクトで環境変数を.envから読み込めないときに確認すること](https://qiita.com/wakeupsloth/items/ec19b9fbfddfb1cd58bb)

## まとめ
データベースの知識を用いずにユーザーのログイン機能を実装できるのはメチャクチャ便利。
他にも色々機能あるみたいなので、触りながら理解を進めていきたい。
もし、`Auth.js`の解釈で間違っているところがあれば、指摘をお願いします。

## Github
Issue: [Login function](https://github.com/kaibara/calculator/issues/9)
PullRequest: [feat: Create Login Function](https://github.com/kaibara/calculator/pull/14)

## 参考資料
全般: [10分でできるReact+FirebaseのGoogleAuth](https://qiita.com/HorieH/items/8b4b1c4807e1eb6fcb0a)
Firebaseについて: [Firebaseの始め方](https://qiita.com/kohashi/items/43ea22f61ade45972881)
Baasについて: [BaaSからSaaSまで！いま一度、クラウドサービスの違いを整理しよう](https://blog.mbaas.nifcloud.com/entry/diffirentofbaasandsaas)
`componentDidMount`について: [5分で理解する React.js](https://qiita.com/tomzoh/items/7fabe7cb57dd96425867#componentdidmount)
`GoogleAuthProvider`について: [Google ログインと JavaScript を使用して認証する](https://firebase.google.com/docs/auth/web/google-signin?hl=ja)
`displayName`について: [Firebase でユーザーを管理する](https://firebase.google.com/docs/auth/web/manage-users?hl=ja)
`.env`の読み込みについて: [create-react-appのプロジェクトで環境変数を.envから読み込めないときに確認すること](https://qiita.com/wakeupsloth/items/ec19b9fbfddfb1cd58bb)