2
votes

The problem is that the vue-router's beforeEnter is triggered earlier than the beforeCreate hook in the main.js and have second delay, while after reload the vuex action set the user in state. This results in the user being bounced to the login page.

How can I delay vue-router's beforeEnter check until vuex set the authorized user in state.

router.js

import Vue from 'vue'
import Router from 'vue-router'
import Home from '../views/Home.vue'
import auth from './auth'

Vue.use(Router)

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/reservations',
      name: 'Reservations',
      component: () => import('@/views/Reservation/Reservations.vue'),
      beforeEnter: auth
    }
  ]
})

auth.js

import { store } from "../store";

export default (to, from, next) => {
    if(store.getters.user) {
        next()
    } else {
        console.log('auth')
        next('/signin')
    }
}

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router/router'
import {store} from './store'
import firebase from 'firebase/app'
import 'firebase/app'    
import config from './config'    
    
new Vue({
  router,
  store,
    render: h => h(App),
    beforeCreate() {
        firebase.initializeApp(config).firestore().settings({timestampsInSnapshots: true})
        console.log('main')     
        this.$store.dispatch('authCheck')   
    }
}).$mount('#app')

store/user.js

import firebase from 'firebase/app'
import 'firebase/auth'

export default{
    state: {
        user: null
    },
    mutations: {
        setUser (state, payload) {
      state.user = payload
        }       
  },
    actions: {
        authCheck({ commit }) {
            commit('setLoading', true)
            firebase.auth().onAuthStateChanged((user) => {              
                if(user){
                    commit('setUser', {
                        id: user.uid,
                        name: user.displayName,
                        email: user.email
                    })
                    commit('setLoading', false)
                }
            })
        },      
        logout({commit}) {
            firebase.auth().signOut()
            commit('setUser', null)
        }
    },
    getters: {
        user (state) {
            return state.user
        }
    }
}

In the console I see first 'auth' from beforeEnter check, and then 'main' from beforeCreate. How to trigger an 'authCheck' before router's check

1
You could try to grab the User Instance with a Firebase Function like onauthstatechange or currentuser without using the Vuex at all.Badgy

1 Answers

0
votes

In your auth.js file instead of monitoring the store, you should wait for the authStateChanged event, then when you receive the user from firebase do your processing then.

auth.js

export default (to, from, next) => {
  firebase.auth().onAuthStateChanged(function (user) {       
    if (user)         
      next();        
    else          
      next('/signin');        
  });
}