0

I am trying to wrap my head around Navigation Guards for vue.js. I tried to follow the example but I think I am falling short in connecting my State (store.js) to my Router (routes.js). In my Login.vue component I try and push to a new route after the loadUser has dispatched to the State and subsequently the isLoggedIn is updated to true. In the vue components I use mapState do I need to do the same thing here in routes.js. Or maybe there is a better way to do this. To give a full picture I am using a vue frontend and laravel backend with Sanctum.

Extract from routes.js

const routes = [
    {
        path: '/',
        component: Login,
        name: 'login'
    },
    {
        path: '/dashboard',
        component: Dashboard,
        name: 'dashboard',
        meta: { requiresAuth: true }
    },
]

const router = new VueRouter({
    mode: 'history',
    routes // short for `routes: routes`
});

router.beforeEach((to, from, next) => {
    // if (to.matched.some(record => record.meta.requiresAuth)) {
    if (to.meta.requiresAuth) {
        if (store.state.isLoggedIn) {
            next();
        } else {
            next({
                name: 'home'
            });
        }
    } else {
        next();
    }
});

export default router;

Extract from store.js

export default {
    state : {
        isLoggedIn: false,
    }
}

Extract from Login.vue

methods : {
        async login() {
            this.loading = true;
            this.errors = null;

            try {
                await axios.get('/sanctum/csrf-cookie');
                await axios.post('/login', this.user);

                logIn();
                this.$store.dispatch('loadUser');
                this.$router.push({ name: 'logbook'});

            } catch (error) {
                this.errors = error.response && error.response.data.errors;
            }

            this.loading = false;
        }
    },
1
  • Maybe I should move the redirect from the vue component to router? Commented Apr 15, 2020 at 18:24

1 Answer 1

2

If you want to access/change the Vuex in VueRouter, you must to use the command router.app.store.state....

For example:

const routes = [
  { path: '/', component: Login, name: 'login' },
  { path: '/dashboard', component: Dashboard, name: 'dashboard', meta: { requiresAuth: true } },
];

const router = new VueRouter({
  mode: 'history',
  routes,
});

router.beforeEach((to, from, next) => {
  if (router.app.$store) {
    // Example to access the state
    console.log(router.app.$store.state.isLoggedIn);

    // Example to exec the mutation
    router.app.$store.commit('myMutation', 'myArgs');

    // Example to exec the action (ATTENTION IS ASYNC)
    router.app.$store.dispatch('myAction', 'myArgs');
  }

  if (to.meta.requiresAuth) {
    // ...
  } else {
    next();
  }
});

export default router;

Attention: You must load the Vuex first than VueRouter. Because, when the VueRouter load the Vuex need to be ready. You can change this in main.js:

import Vue from 'vue'
import App from './App.vue'
import store from './store' // FIRST IMPORT
import router from './router' // SECOND IMPORT

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

Other thing, I prefer to control of login in cookies, because the user can open many tabs. It's my opinion, you can to do what you prefer.

Sign up to request clarification or add additional context in comments.

1 Comment

Did this answer solve your problem? Please accept this answer and this will help others people. How to accept an answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.