Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Router beforeEach guard executed before state loaded in Vue created()

If I navigate directly to an admin guarded route, http://127.0.0.1:8000/dashboard/, the navigation is always rejected because the state hasn't yet loaded at the time the router guard is checked.

beforeEach is being executed before Vue created and thus the currently logged in user isn't recognized.

How do I get around this chicken and egg issue?

files below truncated for relevancy

main.js

router.beforeEach((to, from, next) => {
    //
    // This is executed before the Vue created() method, and thus store getter always fails initially for admin guarded routes
    //

    // The following getter checks if the state's current role is allowed
    const allowed = store.getters[`acl/${to.meta.guard}`]

    if (!allowed) {
        return next(to.meta.fail)
    }

    next()
})

const app = new Vue({
    router,
    store,

    el: "#app",

    created() {
        // state loaded from localStorage if available
        this.$store.dispatch("auth/load")
    },

    render: h => h(App)
})

router.js

export default new VueRouter({
    mode: 'history',

    routes: [
        {
            path: '/',
            name: 'home',
            component: () => import('../components/Home.vue'),
            meta: {
                guard: "isAny",
            },
        },

        {
            path: '/dashboard/',
            name: 'dashboard',
            component: () => import('../components/Dashboard.vue'),
            meta: {
                guard: "isAdmin",
            },
        },
    ],
})
like image 867
pymarco Avatar asked Jul 24 '17 21:07

pymarco


1 Answers

Take this.$store.dispatch("auth/load") out of the Vue creation and run it before the Vue is created.

store.dispatch("auth/load")

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

new Vue({...})

If auth/load is asynchronous, then return a promise from it and do your code initialize your Vue in the callback.

store.dispatch("auth/load").then(() => {

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

  new Vue({...})

})
like image 149
Bert Avatar answered Oct 06 '22 23:10

Bert