【Vue】リロードしても大丈夫。そう、vuex-persistedstateならね。

# Vuexで管理しているステートをリロードしても消えないようにする

*[vuex-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate)*というVeux関連パッケージの紹介記事です。すでに同様の記事はありますが、備忘録として自分でまとめた物を残しておきます。

> - [【Vuex】リロードしてもStateの中身を消さずに維持する方法](https://pizzamanz.net/web/vue/vuex-persistedstate/)
> - [Vue基礎：Vuexの永続化対応
](https://qiita.com/chenglin/items/0fd9baf386227a5ca614)

## Vuexではリロードするとステートは初期状態にもどってしまう
VuexはVueインスタンスがもつステート（データ）をストアと呼ばれる管理場所で一括管理して、全てのコンポーネント間でステートを簡易に共有する仕組みを提供してくれます。つまり、あるコンポーネントでステートの値を変更して、他のコンポーネントでそのステートをストアから取得して使うことができます。

しかし、メモリ上に保存されたVeuxのステートは**ブラウザを閉じたり、リロードしたりすると初期状態にリセットされてしまいます**。

例えばVuexを使って入力フォームの値やユーザーが選択したセレクトボックスの値などを管理していた場合、誤って途中でブラウザを閉じたりリロードしたりするとユーザーが入力した値は消えてしまいます。

このようなケースではUX向上のためにステートを維持させた方が良いでしょう。

このようなケースには*vuex-persistedstate*を使うと、VeuxのステートをWebストレージに一旦逃して、リロードした際に読み込んでステートを維持させることが可能です。

## vuex-persistedstateを使う
詳しくは[こちら](https://github.com/robinvdvleuten/vuex-persistedstate#usage-with-vuex-modules)を参照。

nuxtで使う時はpluginとして設定が必要なようです。

### インストール
yarnまたはnpmでインストール出来ます。

```bash
# yarn
yarn add vuex-persistedstate
# npm
npm install --save vuex-persistedstate
```

### 使い方

まず、ストアをモジュールで分けている場合は、vuexの設定で`modules`プロパティに管理対象のモジュールをセットしておく必要があります。（ここでは例として`auth`と`master`というモジュールがあるとします）。大元のVuexの設定ファイル（ここではindex.js）でストアのセッティングをするところにvuex-persistedstateの設定を書いていきます。

vuex-persistedstateの設定はVuexの設定の`plugins`プロパティに書いていきます。最低限設定しておいた方がいいのは**`key`, `paths`, `storage`**プロパティかなと思います。（なくても動くには動く）

`key`はストレージに保存する時のプロパティ名です。デフォルトでは`vuex`ですが、他のアプリとかぶる可能性があるのでユニークなものに変えましょう。

`paths`に管理対象のステートを書きます。値は`<モジュール名>.<ステート>`と書いて、配列に入れます。配列に入れたステートが管理対象になります。pathsを書かなかった場合はデフォルトで全てのステートが対象になります。

`storage`には保存するストレージを指定します。Webストレージ（ローカルストレージ、セッションストレージ）とCookieから選べるようです。

他にもプロパティが色々あるようです。全プロパティは[ここ](https://github.com/robinvdvleuten/vuex-persistedstate#api)から確認出来ます。

次は設定の一例。

```javascript:frontend/stores/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import auth from './auth.js'
import master from './master.js'

Vue.use(Vuex)

// Vuexの設定
export default new Vuex.Store({  
  // ストアをモジュールに分けている場合。vuexのモジュールを指定
  modules: {
    auth,
    master,
  },
  
  // `createPersistedState()`でインスタンス作成。引数に設定を書く
  plugins: [createPersistedState(
    { // ストレージのキーを指定。デフォルトではvuex
      key: 'anyGreatApp',
      
      // 管理対象のステートを指定。pathsを書かない時は`modules`に書いたモジュールに含まれるステート全て。`[]`の時はどれも保存されない
      paths: [
        'auth.isLoggedIn',
        'master.dataSelected'
      ],

      // ストレージの種類を指定する。デフォルトではローカルストレージ
      storage: window.sessionStorage
    }
  )]
})
```

#### 保存先の違い
`storage`の違いは次の通りです。使用用途によって、変えるといいと思います。複数タブでの作業を想定している場合はセッションストレージを選択するといいと思います。タブごとに異なるセッションとして扱われるので、ステートもタブごとに管理出来ます。細かい違いは[CookieとWebStorageとSessionについてのまとめ](https://qiita.com/pipiox/items/95554673ba3b078ac112)を参照。

| 指定できるストレージ |  `storage`プロパティの値 | 保存期間の違いなど             |
|:-----------------:|:------------------:|:------------:|
| ローカルストレージ | `window.localStrage` | 意図的に消さない限りずっと残る  |
| セッションストレージ | `window.sessionStrage` | セッションが切れたらorタブやブラウザを閉じたらリセット          |
| Cookie          | [こちら](https://github.com/robinvdvleuten/vuex-persistedstate#customize-storage)を参照              |  期限を任意に設定できる&容量が小さい(4KB)& HTTP/HTTPSでサーバーに送信される    |    

また、[ローカルストレージのデータを暗号化できるパッケージ](https://github.com/softvar/secure-ls?ref=producthunt)と組み合わせてセキュアに使うこともできるようです。ハッキングされて流出するとまずいようなデータを扱う時はいいかもしれません。
（そもそも、そういったデータは本来Web StorageやCookieに保存すべきではないですが）

## 注意点
ログアウト時に画面のリロードでステートを初期状態にリセットするようにしている場合は、このパッケージを使うと当然リセットは効かなくなります。

その場合、**ログアウトしてもステートはそのままになるので、違うユーザーでログインしても以前のユーザーのステートが残ったまま**になってしまいます。

ステートをリセットするアクション・ミューテーションを作っておいて、ログアウト時に呼び出すようにしておくと良さそうです
（他にステートをまとめてリセットするいい方法があったら教えてください）