GAミント至上主義

Web Monomaniacal Developer.

Vue Router&Firebaseの認証付きページでログアウト後に任意のページに飛ばそうと思ったらハマった話

Vue RouterとFirebase Authenticationで認証が必要なページを作っていたが、ログアウト後に任意のページに飛ばそうと思ってもうまく行かなかった。
いろいろ試したけど、イベントリスナーonAuthStateChangedを多重登録しないよう事前にUnsubscribeしたら大丈夫になった。

SSSS.GRIDMANを見ると原作の内容よりも小学生のときの同級生がグリッドマンの絵つき道具袋を使っていたのを思い出します。

全体的なやり方は下記ページといっしょ。
qiita.com
qiita.com

最終的なコードは下記。
router.jsから抜粋

// 詳しくは公式ドキュメント
// https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged
let onAuthStateChangedUnsubscribe

router.beforeEach((to, from, next) => {
  if (typeof onAuthStateChangedUnsubscribe === 'function') {
    onAuthStateChangedUnsubscribe()
  }
  if (!to.matched.some(record => record.meta.requiresAuth)) {
    next()
  } else {
    onAuthStateChangedUnsubscribe = firebase.auth().onAuthStateChanged(function (currentUser) {
      if (currentUser) {
        next()
      } else {
        next({
          name: 'login'
        })
      }
    })
  }
})

認証にfirebase.auth().onAuthStateChangedのコールバックを使うようになっているが、それがbeforeEachのタイミングではなく、Firebaseをログアウトした瞬間先に動いてしまい全部loginに飛んでしまって、飛ばしたいページには行かなかったもよう。

これに限らず、以前も書いたけどonなんちゃらのイベントリスナ登録系はなんども登録しないように、また何度も登録が必要な場合は以前のを消し、多重登録しないようにするのが大事だと改めて思う。
uyamazak.hatenablog.com

追記

上記参考ページにあるとおり、firebase.auth().currentUserがある場合の処理を追加したら、ムダも減るし、Unsubscribeしなくてもほとんど問題ないような気がしてきた。

let onAuthStateChangedUnsubscribe
router.beforeEach((to, from, next) => {

  if (!to.matched.some(record => record.meta.requiresAuth)) {
    next()
  } else {
    if (firebase.auth().currentUser) {
      next()
      return
    } else {
      if (typeof onAuthStateChangedUnsubscribe === 'function') {
        onAuthStateChangedUnsubscribe()
      }
      onAuthStateChangedUnsubscribe = firebase.auth().onAuthStateChanged(function (currentUser) {
        if (currentUser) {
          next()
        } else {
          next({
            name: 'login'
          })
        }
      })
    }
  }
})

Vue.js入門 基礎から実践アプリケーション開発まで

Vue.js入門 基礎から実践アプリケーション開発まで