Nuxtでデータの保持／状態管理をする【Vuex基礎】

#はじめに
データが大量にあるので複数のDBで管理しており、どこのDBを参照するのか選択させて保持しておきたい場面があり、Vuexを調べて使ってみたのでその備忘録です。
なにかおかしな点や、もっとこうしたほうがいいよ～等あればコメントお願いします！

#Vuexとは？
Vue.js アプリケーションのための状態管理パターン + ライブラリです。
公式の説明がわかりやすいです。公式最高。

https://vuex.vuejs.org/ja/

#使い方
##インストール
以下のコマンドでインストールできます。

```.sh
#npm
npm install vuex --save

#yarn
yarn add vuex
```
##ストアを有効化する
Vuex ストアは Nuxt.js に付属していてすぐに使えますが、デフォルトでは無効化されています。
nuxtのプロジェクト内に`store`というディレクトリがあります。（デフォルトで`README.md`が入っています。）このディレクトリ内に隠しファイルや`README.md`ではないファイルが含まれていたら、ストアが有効化されます。

今回は`dbState.js`というファイルを作成しました。

##store/jsのファイルを編集

以下のように編集してみました。

```dbState.js
//1.データの設定
export const state = () => ({
  selectDb: null
});

//2.データの更新
export const mutations = {
  setDb(state, db) {
    state.selectDb = db;
  }
};

//3.データの取得
export const getters = {
  getDb(state) {
    return state.selectDb;
  }
};
```

　
1.データの設定　
このjsファイル内で持つデータを設定します。vueファイルで言うところの`data(){ return { } }`の中です。
今回はDBを選択させたいのでselectDbとし、デフォルトをnullにしました。
　
2.データの更新
`mutations`（ミューテーション）は、Vuex のストアの状態を変更できる唯一の方法です。
Vuex の状態（state）を第1引数として取得し、実際に状態の変更を行うので、第1引数を`state`、選択したDB情報を第2引数を`db`としました。

　
3.データの取得
このjsファイル内で持つデータを実際に呼び出したいときに使用します。`mutations`に書くこともできますが、ゲッターに書くことでストアの算出プロパティと考えることができるので、分けて書いてみました。


##.vueファイルを編集

```.vue 
<script>
// 呼び出し
  computed: {
    selectedDb() {
        return this.$store.getters['dbState/getDb']
    }
  },

// 更新
  methods: {
    selectDb(db) {
      this.$store.commit('dbState/setDb', db)
    }
  },
</script>
```

呼び出しは　**this.$store.getters['ファイル名/関数名']**
更新は　**this.$store.commit('ファイル名/関数名', 第2引数)**

と書くことで使用できます。

#情報を永続化する
vuexでページ遷移後も情報を保持することができましたが、リロードするとデータが消えてしまいました。stateがリセットされてしまうらしい。。。
`vuex-persistedstate`というプラグインを使うとstateの情報を永続化できるらしいので使ってみます。

##vuex-persistedstateをインストール
以下のコマンドでインストールできます。

```.sh
# npm
npm install --save　vuex-persistedstate

# yarn
yarn add vuex-persistedstate
```
##プラグインの設定

###plugins/persistedstate.jsを編集
pluginsに「persistedstate.js」というファイルを作成し、以下のように書きました

```.js
import createPersistedState from 'vuex-persistedstate'

export default ({ store }) => {
  createPersistedState({
    key: '任意の名前',　
    storage: window.sessionStorage
  })(store)
}
```

`key`はストレージキーです。デフォルトは、vuexになっているので基本的に指定しましょう。
`storage`は、ストレージの種類です。デフォルトはローカルストレージです。

`storage`は使用用途によって分けたほうがよさそうです。

| ストレージ |  `storage`プロパティの値 | 違い          |
|:-----------------|:------------------|:------------|
| ローカルストレージ | window.localStrage| 意図的に消さない限りずっと残る  |
| セッションストレージ | window.sessionStrage | セッションが切れたとき、タブやブラウザを閉じたときにリセットされる         |

###nuxt.config.jsを編集
以下のように書きました。

```.JS
  plugins: [
    { src: '~/plugins/persistedstate.js', ssr: false}
  ],
```

##注意点
データの永続化というくらいですから、ずっと残ってしまうトラブルも発生します。
今回は`sessionStrag`を使用したのでセッションが切れたり、タブやブラウザを閉じたら消えますが、そうしない場合は情報が残ってしまいます。ステートを初期化するミューテーションを作成して、ログアウト時などに毎回呼び出すなど対策が必要です。

##永続化参考サイト
参考にしたサイト載せておきます
[【Nuxt.js】storeを永続化する](https://zenn.dev/kokota/articles/3eaf6de2a22e29)
[vuexでリロードされても情報を永続化できるvuex-persistedstateの使い方](https://devsakaso.com/vuex-persistedstate-to-keep-data-after-reloading/)
[【Vue】リロードしても大丈夫。そう、vuex-persistedstateならね。](https://qiita.com/_masa_u/items/b58b92c283f4e770e094)

#追記
2021.09.14 追記：
自分のこの記事を参考に、別のプロジェクトで利用しようとしたらエラーが２つでた。

```
vue.runtime.esm.js?2b0e:619 [Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render
```

```
client.js?06a0:103 TypeError: Cannot read properties of undefined (reading 'toLowerCase')
```

調べたところ、**ローカルストレージはブラウザ（クライアントサイド）の機能のため、Nuxt.jsのモードをSSR（サーバサイドレンダリング）ではなくSPA（シングルページアプリケーション）に変更しないと動かないらしい**

`nuxt.config.js`ファイルで`mode`の設定を`spa`に変更することで治りました。

```nuxt.config.js
export default {
  mode: 'spa', // ここをuniversalからspaに変更

  /*
  ** Headers of the page
  */
  head: {
    titleTemplate: '%s - ' + process.env.npm_package_name,
～略～
}
```

ただこれが最善なのかはわかりませんが。。。別の解決法が分かる方よかったらコメントいただけると嬉しいです。


#さいごに
今回は自分が今使うにあたって必要な最低限についてのみでしたが、誰かの参考になれば嬉しいです。

最後まで読んでいただきありがとうございます！