【Nuxt.js】firebase基礎編(Auth版)：メールアドレスログインをできるようにしよう

2020/10/12 訂正
store内で$routeを使用していましたが、
そもそもstoreで使用不可でした😨
申し訳ございません！
こちらもWPにて詳細ご確認お願い致します❗️🙏

🎈 この記事はWPへ移行しました
【Nuxt.js】firebase基礎編(Auth版)：メールアドレスログインをできるようにしよう

# 前置き
![login4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/2826fdc0-1ec2-566f-61c9-c9e16844eb8a.gif)
ログイン機能があると
サービスの幅が広がりますよね🌟
でも難しそう😔
そう思っていませんか？💡
それを解決するのがfirebase Auth！
これを使えば簡単に実装できます💕

今回はログインの実装がメインです！
そのため新規アカウント作成画面は作りません。
まずauthに慣れていきましょう🎶

🍒アプリ開発基礎編
　追加オプション機能では
　アカウント作成などもやっていきます！
https://note.com/aliz/n/n8411db2c9a20

【使うもの】
・Firebase Authentication
・Vuex(ログイン状態の保持)

# Step1: firebase authの準備

まずはfirebaseでプロジェクトを作成し、
ログイン方法の設定をしていきます🍒

**プロジェクトの作成方法はこちら**
step1-5. アカウントを選択
プロジェクト概要画面まで
https://note.com/aliz/n/nacc97fe7d019#Ls0Km


・プロジェクトができたら
　サイドメニューのAuthenticationを選択
　ログイン方法を設定を選択

<img width="901" alt="auth1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/579e5357-322e-a362-2e7a-9574bb913f53.png">

・メールを選択

<img width="701" alt="Frame 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/55aea0d2-d3bc-df52-2808-f71ed6ab8377.png">

・メールでのログインを有効にし、保存

<img width="701" alt="Frame 3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/989f0989-7fc7-b594-2e96-70183bff3fb2.png">

・usersタブに戻りユーザーを追加

<img width="850" alt="Frame 4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/8e97fc13-b8f3-a634-b924-046753dd66cd.png">

登録できるとユーザー情報が表示されます🌟

<img width="850" alt="Frame 5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/eb01244b-e69a-9839-cbed-96721bb4ef40.png">

# Step2: firebaseとの連携

こちらの記事の
Step3、Step4をご覧ください👀
https://note.com/aliz/n/nacc97fe7d019#Ls0Km


```plugin/firebase.js
import firebase from "firebase/app"

if (!firebase.apps.length) {
firebase.initializeApp({
 apiKey: "貼り付け",
 authDomain: "貼り付け",
 databaseURL: "貼り付け",
 projectId: "貼り付け",
 storageBucket: "貼り付け",
 messagingSenderId: "貼り付け",
 appId: "貼り付け",
 measurementId: "貼り付け"
})
}

export default firebase
```

# Step3: ログイン機能の実装
![login.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/b9bdf608-5f9d-d9bc-1fd1-b792b66279a8.gif)
公式ガイドのこちらを見てみましょう👀
Get Startedタブから順番に進めてみます🌸
ログインフォームを作って
methodsにこの関数を書けば良いわけですね💡
signInWithEmailAndPassword()


https://firebase.google.com/docs/auth/web/start#sign_in_existing_users

```index.vue
<template>
 <div class="page">
   <form
     class="form"
     @submit.prevent
   >
     <label class="label">
       <span class="label">
         email
       </span>
       <input
         class="input"
         type="text"
         v-model="email"
       >
     </label>
     <label class="label">
       <span class="label">
         password
       </span>
       <input
         class="input"
         type="password"
         v-model="password"
       >
     </label>
     <button
       class="button"
       type="submit"
       @click="login"
     >
       Login
     </button>
   </form>
 </div>
</template>

<script>
import firebase from '~/plugins/firebase'

export default {
 data() {
   return {
     email: '',
     password: ''
   }
 },
 methods : {
   login() {
     firebase.auth().signInWithEmailAndPassword(this.email, this.password)
     .then(user => {
       // eslintがある場合は
       // 引数にuser追加とeslint-disable-lineの記載
       console.log('成功！')// eslint-disable-line
     }).catch((error) => {
       alert(error)
     });
   },
 }
}
</script>

<style lang="scss">
 .Login {
   > .form {
     > .button {
       display: block;
     }

     > .label {
       > .input {
         display: block;
         border: 1px solid blck; 
       }
     }
   }
 }
</style>
```

# Step4: Vuexに移行

今のままだとログインするだけなので
Vuexを使うメリットがないのですが、
ログインしたという状態を
保持するための準備です！

```index.vue
<template>
 <div class="page">
   <form
     class="form"
     @submit.prevent
   >
     <label class="label">
       <span class="label">
         email
       </span>
       <input
         class="input"
         type="text"
         v-model="email"
       >
     </label>
     <label class="label">
       <span class="label">
         password
       </span>
       <input
         class="input"
         type="password"
         v-model="password"
       >
     </label>
     <button
       class="button"
       type="submit"
       @click="login"
     >
       Login
     </button>
   </form>
 </div>
</template>

<script>
import firebase from '~/plugins/firebase'

export default {
 data () {
   return {
     email: '',
     password: '',
   }
 },
 methods : {
   login (email, password) {
     this.$store.dispatch('login', {email: this.email, password: this.password})
   },
 }
}
</script>
```

```store/index.js
import firebase from '~/plugins/firebase'

export const state = () => ({
})

export const getters = {
}

export const actions = {
 login(context, payload) {
   firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
     .then(user => {
         console.log('成功！')
       }).catch((error) => {
         alert(error)
       })
 },
}

export const mutations = {
}
```

**【解説】**
index.vueで入力した
email, passwordを引数で渡します🎁
index.jsのactionsでは
第一引数が必ずcontextになるので
第二引数としてemail, passwordを受け取ります📩

# Step5: ユーザーデータの取得

![login2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/472fb84a-810e-1421-d8da-ea93dfbf112d.gif)

ログインができたら
ユーザー情報を表示したいので
情報を取得してきましょう！📩
こちらを見てみましょう👀
onAuthStateChanged()

https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data

```index.js
import firebase from '~/plugins/firebase'

export const state = () => ({
 user: {
   uid: '',
   email: '',
 },
})

export const getters = {
 user: state => {
   return state.user
 }
}

export const actions = {
 login({ commit }, payload) {
   firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
     .then(user => {
         console.log('成功！')
         firebase.auth().onAuthStateChanged(function (user) {
           if (user) {
             commit('getData', { uid: user.uid, email: user.email })
           }
         })
       }).catch((error) => {
         alert(error)
       })
 },
}

export const mutations = {
 getData (state, payload) {
   state.user.uid = payload.uid
   state.user.email = payload.email
 }
}
```

**【解説】**
それぞれの役割を確認したい方はこちら
https://note.com/aliz/n/n6f4a42bce5b5

**🌷state🌷**
　・取得情報の格納場所

**🌷getters🌷**
　・stateを取得

**🌷actions🌷**
　・ログインと同時に取得したいので
　　ログイン成功時(.then)に記載
　　→step7でログインと取得で
　　　切り分けるように調整をします✂︎
　・ガイド参考
　　これで取得ができます！
　　ID：user.uid
　　💌：user.email
　　引数に直接user.uidとは書けないので
　　一旦uidと置き換えます
　・commit
　　ログイン情報をstateに入れるため
　　mutationsを呼び出します

**🌷mutations🌷**
　取得した情報でstateを書き換えます

**【index.vue】**
computed users()でgettersを呼び出し表示

# Step6: ログイン情報保持

![login3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/bdde9371-d55e-d765-67c8-e9411cb81aac.gif)

先ほどログインが成功した時に
ユーザーデータを取得できたので
こちらを追加しましょう！
**・stateにログイン状態の真偽値を追加**
　→ログインできたらtrueに変更
**・v-ifで真偽値による出し分け**
　→ログインtrue, ログアウトfalse

```index.js
import firebase from '~/plugins/firebase'

export const state = () => ({
 user: {
   uid: '',
   email: '',
　　// ログイン状態の真偽値を追加
   login: false,
 },
})

export const getters = {
 user: state => {
   return state.user
 }
}

export const actions = {
 login({ commit }, payload) {
   firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
     .then(user => {
         console.log('成功！')
         firebase.auth().onAuthStateChanged(function (user) {
           if (user) {
             commit('getData', { uid: user.uid, email: user.email })
             // ユーザー情報の取得と同時にcommitで真偽値の切り替え
             commit('switchLogin')
           }
         })
       }).catch((error) => {
         alert(error)
       })
 },
}

export const mutations = {
 getData (state, payload) {
   state.user.uid = payload.uid
   state.user.email = payload.email
 },
 // 真偽値を切り替えるmutationsを追加
 switchLogin (state) {
   state.user.login = true
 },
}
```

```index.vue
<template>
 <div class="page">
   <p
     v-if="user.login"
     class="text"
   >
     {{ user }}
   </p>
   <form
    v-else
   >
    // 省略
   </form>
 </div>
</template>

<script>
import firebase from '~/plugins/firebase'

export default {
 computed: {
   user () {
     return this.$store.getters['user']
   },
 },
 data () {
   return {
     email: '',
     password: '',
   }
 },
 methods : {
   login (email, password) {
     this.$store.dispatch('login', {email: this.email, password: this.password})
   },
 }
}
</script>
```

# Step7: ログイン保持のチェック✅＆調整

![login4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/e9a5f807-d828-3ed7-0024-db033914efc8.gif)

最後にcomponentsに移動させ
全てのコンポーネントで
ログインが保持されるかチェック✅
リロードしない限り
保持されることが確認できます✨👀

また、store/index.jsのactionsを
役割で切り分けてみます✂︎

**【Login.vue】**
index.vueをまるまるコピペ
・fibaseのimportが不要→削除
・全体のdiv class="login"に変更

```Login.vue
<template>
 <div class="login">
   <p
     v-if="user.login"
     class="text"
   >
     {{ user }}
   </p>
   <form
     v-else
     class="form"
     @submit.prevent
   >
     <label class="label">
       <span class="label">
         email
       </span>
       <input
         class="input"
         type="text"
         v-model="email"
       >
     </label>
     <label class="label">
       <span class="label">
         password
       </span>
       <input
         class="input"
         type="password"
         v-model="password"
       >
     </label>
     <button
       class="button"
       type="submit"
       @click="login"
     >
       Login
     </button>
   </form>
 </div>
</template>

<script>
export default {
 computed: {
   user () {
     return this.$store.getters['user']
   },
 },
 data () {
   return {
     email: '',
     password: '',
   }
 },
 methods : {
   login (email, password) {
     this.$store.dispatch('login', {email: this.email, password: this.password})
   },
 }
}
</script>
```

```index.vue
<template>
 <div class="page">
   <Login />
   <p
     v-if="user.login"
     class="text"
   >
     ログインに成功！
   </p>
 </div>
</template>

<script>
import Login from '~/components/Login.vue'

export default {
 components: {
   Login: Login,
 },
 computed: {
   user () {
     return this.$store.getters['user']
   },
 },
}
</script>
```

**【store/index.js】**
・ログイン(login)
・ログイン情報の取得(checkLogin)
で切り分けました✂︎
actions内で別のactionsを
dispatchで呼び出せます📣

```store/index.js
import firebase from '~/plugins/firebase'

export const state = () => ({
 user: {
   uid: '',
   email: '',
   login: false,
 },
})

export const getters = {
 user: state => {
   return state.user
 }
}

export const actions = {
 login({ dispatch }, payload) {
   firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
     .then(user => {
         console.log('成功！')
         dispatch('checkLogin')
       }).catch((error) => {
         alert(error)
       })
 },
 checkLogin ({ commit }) {
   firebase.auth().onAuthStateChanged(function (user) {
     if (user) {
       commit('getData', { uid: user.uid, email: user.email })
       commit('switchLogin')
     }
   })
 },
}

export const mutations = {
 getData (state, payload) {
   state.user.uid = payload.uid
   state.user.email = payload.email
 },
 switchLogin (state) {
   state.user.login = true
 },
}
```