LoginSignup
9
10

More than 3 years have passed since last update.

VuexですべてのStateを初期化する

Posted at

はじめに

ログアウトをしても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に引数を渡せるようにして、特定のモジュールのみ初期化するということもできます。
けっこう重い処理なので使い所は要注意です。

参考

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10