【３】Firebase AuthenticationとNuxt.jsのVuexで認証機能を実現する(1)

## はじめに

いよいよアプリケーションの実装に入ります。
まずはgoogleアカウントでログインできる機能を準備していくつもりです。今回はモックで。

### eslintのルール設定

現状のeslintの設定とフォーマッターがうまく噛み合っていないので、エラーになるルールをとりあえず潰しておく。
本当はフォーマッター側を直すべきだが、現状わかっていない。

```.eslintrc.js
module.exports = {
  // 省略
  rules: {
    "space-before-function-paren": "off",
    "vue/singleline-html-element-content-newline": "off",
    "vue/html-self-closing": "off",
    quotes: "off",
    semi: "off"
  }
}
```

## 手順

### Vuexに慣れる

Vueは知っていてもVuex（Nuxt.js上のVuex）は未経験なので、いったん基本に立ち返って学習します。
https://vuex.vuejs.org/ja/guide/
https://nuxtjs.org/guide/vuex-store
https://qiita.com/y-miine/items/028c73aa3f87e983ed4c

まずはユーザの認証状況を管理するためのユーザモジュールを準備する。
Nuxt.jsではすべて `store` ディレクトリ以下に置くらしい。

```store/user.js
export const state = () => ({
  isSignedIn: false // ログインしているか
})
```

`isSignedIn` の値を読み込むには、 `$store.state.user.isSignedIn` でOK。
ためしに `pages/index.vue` に手を入れてみる。

```diff
        <v-card-title class="headline">
          Welcome to the Vuetify + Nuxt.js template
        </v-card-title>
        <v-card-text>
+          <p v-if="$store.state.user.isSignedIn">isSignedIn</p>
+          <p v-if="!$store.state.user.isSignedIn">isNotSignedIn</p>
           <p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p>
```

`yarn run dev` でローカル環境を立ち上げて確認してみると、 "isNotSignedIn" が出てくるはず。

またstateに直接アクセスするのに抵抗があって調べてみると、stateを評価するために `getters` というのが使えるらしい。

```store/user.js
export const state = () => ({
  isSignedIn: false // ログインしているか
})

// ゲッター。computedのような感じで、変数が変わったときだけ再評価される。
export const getters = {
  isAuthenticated: state => !!state.isSignedIn
};
```

`index.vue` のほうでは、次のように記述ができる。

```diff
        <v-card-title class="headline">
          Welcome to the Vuetify + Nuxt.js template
        </v-card-title>
        <v-card-text>
+          <p v-if="$store.getters['user/isAuthenticated']">isSignedIn</p>
+          <p v-if="!$store.getters['user/isAuthenticated']">isNotSignedIn</p>
           <p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p>
```

さらに `mapGetters` というヘルパーメソッドを使うことで、より簡単にgettersを利用できる。

```diff
        <v-card-title class="headline">
          Welcome to the Vuetify + Nuxt.js template
        </v-card-title>
        <v-card-text>
+          <p v-if="isAuthenticated">isSignedIn</p>
+          <p v-if="!isAuthenticated">isNotSignedIn</p>
           <p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p>

//省略

<script>
export default {
  components: {
    Logo,
    VuetifyLogo
  },
+  computed: {
+    // userモジュールのisAuthenticatedを使えるようにする
+    ...mapGetters("user", ["isAuthenticated"])
+  }
}
</script>
```

### 状態を更新する

Vuexのミューテーションとアクションを追加して、状態を更新できるようにする。

```/store/user.js
export const state = () => ({
  isSignedIn: false // ログインしているか
});

// ゲッター。computedのような感じで、変数が変わったときだけ再評価される。
export const getters = {
  isAuthenticated: state => !!state.isSignedIn
};

// ミューテーション。ストアの状態を変更する。コミットが必要。
export const mutations = {
  setSignInState(state, isSignedIn) {
    state.isSignedIn = isSignedIn;
  }
};

// アクション。状態を変更するのではなく、ミューテーションをコミットする。
// 任意の非同期処理を含むことができる。
export const actions = {
  async signIn({ commit }) {
    // ログイン処理。モックなので絶対に成功したことにする。
    const isSignedIn = await true;
    commit("setSignInState", isSignedIn);
  },
  signOut({ commit }) {
    commit("setSignInState", false);
  }
};
```

`mapGetters` 同様に `mapActions` を使って簡単に使えるようにしておく。

```diff
        <v-card-title class="headline">
          Welcome to the Vuetify + Nuxt.js template
        </v-card-title>
        <v-card-text>
+          <p v-if="isAuthenticated">isSignedIn</p>
+          <p v-if="!isAuthenticated">isNotSignedIn</p>
+          <p>
+            <v-btn @click="signIn">signIn</v-btn>
+            <v-btn @click="signOut">signOut</v-btn>
+          </p>
           <p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p>

//省略

<script>
export default {
  components: {
    Logo,
    VuetifyLogo
  },
+  computed: {
+    // userモジュールのisAuthenticatedを使えるようにする
+    ...mapGetters("user", ["isAuthenticated"])
+  },
+  methods: {
+    ...mapActions("user", ["signIn", "signOut"])
+  }
}
</script>
```

## ここまで

https://github.com/koboriakira/sparrow-memo/tree/ver1.3