はじめに
ログアウトをしてもStateに値が残っているため、別のユーザでログインした際に前回の情報を参照できてしまうという問題の対策です。
"vuex": "3.1.1"
やりかた
各モジュールにStateを初期化するAction、Mutationを作成しておくのが定番らしいのですが、面倒なので以下の関数を定義しておきます。
const RESET_STATE = 'RESET_STATE'
function createResetHandler(module: any, name: string) {
const childModules = module.modules
if (childModules) {
for (const key of Object.keys(childModules)) {
createResetHandler(childModules[key], `${name}/${key}`)
}
}
// stateがないmoduleは初期化の必要がないので無視
if (!module.state) {
return
}
// NB: stateは関数で定義しておく
if (typeof module.state !== 'function') {
console.error(`Vuex module state of '${name}' is not a function`)
}
module.mutations = module.mutations || {}
module.actions = module.actions || {}
const mutation = (state: any) => {
Object.assign(state, module.state())
}
module.mutations[RESET_STATE] = mutation
// グローバルにアクションを定義する
const action = {
root: true,
async handler(context: { commit: Function }) {
context.commit(RESET_STATE)
},
}
module.actions[RESET_STATE] = action
}
これをStoreを作成する前に実行しておく
const modules = {
module1,
module2,
...
}
for (const key of Object.keys(modules)) {
createResetHandler(modules[key], key)
}
new Store<State>({ state, mutations, actions, modules })
リセットするとき
logout({ dispatch }) {
// --- ログアウト処理 ---
dispatch(RESET_STATE, undefined, { root: true })
}
解説
stateを関数にしておくことでmodule.state()
を実行すると初期値が返されます。
_actions = { RESET_STATE: [ function, function, function ... ] }
というようにStoreにアクションが登録されているので、dispacth(RESET_STATE, undefined, { root: true })
ですべてのアクションが呼び出されます。
まとめ
RESET_STATE
に引数を渡せるようにして、特定のモジュールのみ初期化するということもできます。
けっこう重い処理なので使い所は要注意です。
参考