I have a bit of a conundrum in my Vue/vuex/vue-router + Firebase app. The bootstrap code is supposed to initialize Firebase, as well as the signed in user (if any) in Vuex:
new Vue({
el: '#app', router, store, template: '<App/>', components: { App },
beforeCreate() {
firebase.initializeApp(firebaseConfig)
// Because the code below is async, the app gets created before user is returned...
.auth().onAuthStateChanged(user => {
this.$store.commit('syncAuthUser', user) // this executes too late...
})
}
})
In my routes, I have
{ path: '/home', name: 'Home', component: Home, meta: { requiresAuth: true } }
as well as
router.beforeEach((to, from, next) => {
let authUser = store.getters.authUser // this is not set just yet...
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!authUser) {
next('signin') // /home will always hit here...
}
next()
}
else {
next()
}
})
Problem
As mentioned in the comments, the app gets the authenticated user too late. So, when you go to /home while logged in, the app will run the beforeEachcheck in the routes... And the user instance will not be available just yet, so it will think that you are not logged in, when in fact you are (it's clear from my computed properties that are properly updated a few moments later).
Question
So, how do I change my code, so that the Vue app gets initialized only after Firebase returns the user and after that user is passed to the Vuex store? Plese let me know if I am doing something completely wrong.
Attempts
- I tried the "unsubscribe" approach; however, its problem is that the
onAuthStateChangedwould only be triggered once. So, if I put my crucialthis.$store.commit('syncAuthUser', user)there, then that code would only execute when the app is created, and not when the user logs out for example. - I also tried a better approach here. I did work for me, but I felt bad wrapping
onAuthStateChangedin anotherPromise, for sure there must be a better way; plus, it seems wrong to place the auth user initialization login in the routes file.