はじめに
ログイン情報を保持したり、パスワードの有効期限が切れていたら更新するまで他のページに遷移させない、などなど、
Vuexを利用し始めると、一度はページのリロードや遷移でstateの値がリセットされる現象に頭を悩ませるのではないでしょうか。
少なくとも私は半日悩みました。
リロードをしても状態を保持するためには、何らかの方法でブラウザに保存する必要があります。
自前でCookieやlocalStorageに保存する処理を実装する事もできますが、ここは先人達に習い便利なパッケージvuex-persistedstate
を利用して楽をしたいと思います。
(Vuexの永続化、stateの永続化で調べると色々と出てきます)
なお、Vueのバージョンは3となります。
vuex-persistedstate
npmを使ってインストールします。
npm install --save vuex-persistedstate
Vuexの設定
今回、authモジュールとして認証関連のstoreを分ける事にしたので、メインのVuexファイルでvuex-persistedstateをプラグインとしてインポートする必要があります。
また、保持したいstateと保持したくないstateがあるので、pathsオプションで保持したいstateを明示的に指定したいと思います。
(保存先はデフォルトのlocalStorageとします)
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import * as root from './root'
import * as auth from './modules/auth'
Vue.use(Vuex)
interface ModulesStates {
auth: auth.State
}
export type RootState = root.State & ModulesStates
export default () =>
new Vuex.Store({
state: root.state() as any,
getters: root.getters,
mutations: root.mutations,
actions: root.actions as any,
modules: {
[auth.name]: auth,
},
plugins: [createPersistedState({
key: auth_info,
paths: [
'auth.isPasswordValid',
'auth.isLoggedIn',
]
})],
})
storeの設定
ログインの状態を保持するisLoggedIn
というstateと、パスワードの状態を保持するisPasswordValid
という二つのstateを用意しました。
export interface State {
isLoggedIn: boolean
isPasswordValid: boolean
}
export const state = (): State => ({
isLoggedIn: false,
isPasswordValid: true,
})
import { MutationTree } from 'vuex'
import { State } from '~/store/modules/auth/state'
export const mutations: MutationTree<State> = {
setLoginState: (state: State, isLoggedIn: boolean) => {
state.isLoggedIn = isLoggedIn
},
setPasswordState: (state: State, isPasswordValid: boolean) => {
state.isPasswordValid = isPasswordValid
},
}
import { GetterTree } from 'vuex'
import { RootState } from '~/store'
import { State } from '~/store/modules/auth/state'
export const getters: GetterTree<State, RootState> = {
isLoggedIn: (state: State) => state.isLoggedIn,
isPasswordValid: (state: State) => state.isPasswordValid,
}
storeの利用
準備が整ったので、実際にstateの値がlocalStorageに保存されているか確認します。
ログイン時に、下記の様にstateに値をセットします。
store.commit('auth/setLoginState', true)
store.commit('auth/setPasswordState', true)
Chromeの開発ツールでlocalStorageを確認すると、下記の様に値が保存されていることが確認できます。
キー | 値 |
---|---|
auth_info | {"auth":{"isPasswordValid":true,"isLoggedIn":true}} |
middlewareの実装
認証が必要な画面で共通して利用できる様に、ログイン画面やパスワード更新画面へのリダイレクト処理をミドルウェアに切り出しました。
import { Context } from '@nuxt/types'
export default function ({ store, redirect }: Context) {
if (!store.getters['auth/isLoggedIn']) redirect('/login')
if (!store.getters['auth/isPasswordValid']) redirect('/passwordUpdate')
}
おわりに
実際にはAPI等のレスポンスに応じたアクセス制御を行うのですが、
APIを実行する前段階でのフロントエンド側の制御として参考にしていただければと思います。