[Expo + React Native]Firebase Auth(メールアドレス)の実装

# 今回の実装
- メールアドレスで新規登録
- メールアドレスでログイン

上記の実装を行う

# 実装手順
1. Firebaseのプロジェクトを作成する
2. プロジェクトに**Webアプリケーション**を登録する(IOS,Androidではないので注意)
3. 環境設定ファイルを作成し、Firebaseの値をセットする
4. Firebaseのライブラリをインストール
5. 設定情報を読み込み、Firebaseをイニシャライズする
6. 新規登録機能の実装
7. ログイン機能の実装

# 実装
## 1.Firebaseのプロジェクトを作成する
Consoleにアクセスして、プロジェクトの作成を行う(設定などは全てデフォルトのままでOK)
[Firebase Console](https://console.firebase.google.com/?hl=JA)

## 2.プロジェクトにWebアプリを登録する
アプリのニックネームはなんでもOKです(Firebase Hostingも必要ないです)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/2e018b31-62fc-b6cc-04e3-c60d69a6ba19.png)

こちらのapiKey〜measurementIdは後ほど環境設定ファイルの作成で使用するので控えておく
![Group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/e532a8e9-aa41-9c05-24bf-75c451bf8398.png)

## 3.環境設定ファイルを作成し、Firebaseの値をセットする
プロジェクトフォルダーに以下のように環境設定ファイル(env.json)を作成する
設定ファイルの内容を知られると、自分のプロジェクトを操作される可能性があるので、
下記のenv.jsonはGithubには上げないようにする。

```env.json
{
  "FIREBASE_API_KEY": "自分のapiKey",
  "FIREBASE_AUTH_DOMAIN": "自分のauthDomain",
  "FIREBASE_DB_URL": "自分のdatabaseURL",
  "FIREBASE_PROJECT_ID": "自分のprojectId",
  "FIREBASE_STORAGE": "自分のstorageBucket",
  "FIREBASE_SENDER_ID": "自分のmessagingSenderId",
  "FIREBASE_APP_ID": "自分のappId",
  "FIREBASE_MEASUREMENT_ID": "自分のmeasurementId"
}
```

## 4.Firebaseのライブラリをインストール
以下のコマンドを実行して、Firebaseをインストールする
`npm install --save firebase`

## 5.設定情報を読み込み、Firebaseをイニシャライズする
App.jsに3で作成したenv.jsonと4でインストールしたfirebaseをimportし、firebaseのイニシャライズを行う

```App.js
import firebase from 'firebase';
import env from './env.json';

// 省略

const firebaseConfig = {
  apiKey: env.FIREBASE_API_KEY,
  authDomain: env.FIREBASE_AUTH_DOMAIN,
  databaseURL: env.FIREBASE_DB_URL,
  projectId: env.FIREBASE_PROJECT_ID,
  storageBucket: env.FIREBASE_STORAGE,
  messagingSenderId: env.FIREBASE_SENDER_ID,
  appId: env.FIREBASE_APP_ID,
  measurementId: env.FIREBASE_MEASUREMENT_ID,
};

firebase.initializeApp(firebaseConfig);

// 省略
```

## 6. 新規登録機能の実装

### 新規登録画面
![Simulator Screen Shot - iPhone 11 Pro Max - 2020-07-18 at 18.52.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/3d037adb-f138-68ec-cb17-a98d75f924d3.png)

### 実装コード

```SignUpScreen.js
import React from 'react';
import { StyleSheet, View, Text, TextInput, TouchableHighlight } from 'react-native';
// firebaseのimport
import firebase from 'firebase';

class SignUpScreen extends React.Component {
  // emailとpasswordのstateを用意
  state = {
    email: '',
    password: '',
  }
  
  // 新規登録ボタンを押した時の処理
  handleSubmit() {
    // このメソッドを呼ぶだけ
    firebase.auth().createUserWithEmailAndPassword(
      this.state.email,
      this.state.password,
    ).then((user) => {
      console.log(user);
      // 完了時の処理
    }).catch((error) => {
      console.log(error);
      // 失敗時の処理
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.title}>新規登録</Text>
        <TextInput
          style={styles.input}
          value={this.state.email}
          onChangeText={(text) => { this.setState({ email: text }); }}
          autoCapitalize="none"
          autoCorrect={false}
          placeholder="Email"
        />
        <TextInput
          style={styles.input}
          value={this.state.password}
          onChangeText={(text) => { this.setState({ password: text }); }}
          autoCapitalize="none"
          autoCorrect={false}
          placeholder="Password"
          secureTextEntry
        />
        <TouchableHighlight underlayColor="#C70F66" style={styles.button} onPress={this.handleSubmit.bind(this)}>
          <Text style={styles.buttonTitle}>新規登録する</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    width: '100%',
    padding: 24,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 28,
    alignSelf: 'center',
    marginBottom: 24,
  },
  input: {
    backgroundColor: '#ddd',
    height: 48,
    marginBottom: 16,
    borderWidth: 1,
    borderColor: '#ccc',
    padding: 8,
  },
  button: {
    height: 48,
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#000',
    width: '60%',
    alignSelf: 'center',
  },
  buttonTitle: {
    fontSize: 18,
    color: '#fff',
  },
});

export default SignUpScreen;
```

新規登録の実装部分は以下のコードを記述するだけなので、かなり簡単に実装が可能

```SignUpScreen.js
// このメソッドを呼ぶだけ
    firebase.auth().createUserWithEmailAndPassword(
      this.state.email,
      this.state.password,
    ).then((user) => {
      console.log(user);
      // 完了時の処理
    }).catch((error) => {
      console.log(error);
      // 失敗時の処理
    });
```

## 7. ログイン機能の実装
ログインも新規登録とほぼ同じで、呼ぶメソッドが少し異なるだけです。

### 画面
![Simulator Screen Shot - iPhone 11 Pro Max - 2020-07-18 at 18.51.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/514870/b787229b-9e84-ab8e-400e-4d3be5bd3830.png)

### 実装コード

```LoginScreen.js
import React from 'react';
import firebase from 'firebase';
import { StyleSheet, View, Text, TextInput, TouchableHighlight } from 'react-native';

class LoginScreen extends React.Component {
  state = {
    email: '',
    password: '',
  }

  handleSubmit() {
    firebase.auth().signInWithEmailAndPassword(
      this.state.email,
      this.state.password,
    ).then((user) => {
      console.log(user);
      this.props.navigation.navigate('Home');
    }).catch((error) => {
      console.log(error);
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.title}>ログイン</Text>
        <TextInput
          style={styles.input}
          value={this.state.email}
          onChangeText={(text) => { this.setState({ email: text }); }}
          autoCapitalize="none"
          autoCorrect={false}
          placeholder="Email"
        />
        <TextInput
          style={styles.input}
          value={this.state.password}
          onChangeText={(text) => { this.setState({ password: text }); }}
          autoCapitalize="none"
          autoCorrect={false}
          placeholder="Password"
          secureTextEntry
        />
        <TouchableHighlight underlayColor="#C70F66" style={styles.button} onPress={this.handleSubmit.bind(this)}>
          <Text style={styles.buttonTitle}>ログインする</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    width: '100%',
    padding: 24,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 28,
    alignSelf: 'center',
    marginBottom: 24,
  },
  input: {
    backgroundColor: '#ddd',
    height: 48,
    marginBottom: 16,
    borderWidth: 1,
    borderColor: '#ccc',
    padding: 8,
  },
  button: {
    height: 48,
    borderRadius: 4,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#000',
    width: '60%',
    alignSelf: 'center',
  },
  buttonTitle: {
    fontSize: 18,
    color: '#fff',
  },
});

export default LoginScreen;
```

新規登録と異なるのはこちらのメソッドのみです。

```LoginScreen.js
    firebase.auth().signInWithEmailAndPassword(
      this.state.email,
      this.state.password,
    ).then((user) => {
      console.log(user);
      this.props.navigation.navigate('Home');
    }).catch((error) => {
      console.log(error);
    });
```

# 最後に
個人的にはIOSとAndroidアプリで各々設定ファイルを登録するものだと思っていたので、
Firebaseの設定がWebだけだったのが衝撃でした。
Expo + React Nativeの仕組みがまだあまり理解できていないので、
そのあたりも学習していこうと思う