Search code examples
javascriptvue.jsvuejs2vuexvuetify.js

Vue router's before each doesn't work after hard refresh


I'm having a new issue with Vue.js, I'm using my loggin page to log in my app, everything works fine, if it's an admin profile it goes to the admin page, regular user to the home page.

But if I'm an admin and I hard refresh the page with F5 then I can't go anymore to the admin page. I think I understand I have a problem with the calling order of my plugins and that I need to call my localStorage before the router but I'm not using a plugin for the localStorage.

Here is the code, first my beforeEach function from the router:

router.beforeEach(async (to, from, next) => {
  let user =  await store.getters.userInSession;
  let token = await store.getters.getToken;

  if(to.matched.some(record => record.meta.requiresAuth) && token == '') {
    next({ name : 'Connexion'})
  } else if (to.matched.some(record => record.meta.is_admin) && user.role  != "Admin"){
    next({ name: 'Tableau de bord'})
  } else if(to.matched.some(record => record.meta.guest) && token != '') {
    next({ name: 'Tableau de bord'})
  } else {
    next();
  }
})

Then here is how I access my localStorage from the vuex:

import Vue from 'vue';
import router from '../../router';

const state = {
    token: localStorage.getItem('token'),
    user: localStorage.getItem('user'),
    errors: []
};

const getters = {
    isAuthenticated: state => !!state.token,
    userInSession: state => {
        return state.user;
    },
    isAdmin: state => {
        return state.user ? state.user.role == 'Admin' : false
    },
    getToken: state => {
        return state.token ? state.token : "";
    }
};

I've tried to use vue-localstorage and put it in my Vue instance before the router but I don't even understand how to set it globally. It doesn't get recognised as a pluginObject so I cannot do a Vue.use with this one.

Anyway I tried this:

import Vue from 'vue';
import App from './App.vue';

import router from './router';
import store from './store';
import VueLocalStorage from 'vue-localstorage';
import vuetify from './plugins/vuetify';

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

Last thing I think is related but I'm not sure, I'm showin my user info in my and after a hard refresh it's also desappearing... I call it like so:

<v-list-item two-line>
    <v-list-item-avatar>
        <!-- <v-img max-width="40px" contain src="../assets/P.png" class="ma-2"></v-img> -->
        <img src="https://randomuser.me/api/portraits/men/32.jpg">
    </v-list-item-avatar>

    <v-list-item-content>
        <v-list-item-title>{{userInSession.prenom | capitalize}} {{userInSession.nom | capitalize}}</v-list-item-title>
        <v-list-item-subtitle>{{userInSession.role | capitalize}}</v-list-item-subtitle>
    </v-list-item-content>
</v-list-item>

It's the same object I'm accessing from the vuex. Would appreciate some help if someone has a clue.


Solution

  • I solved my issue by creating a hook where my vue instance is created:

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

    I just initialise my store in a mutator like so:

    INITIALISATION_STORE(state) {
            if(localStorage.getItem('token')){
                state.token = localStorage.getItem('token')
            }
            if(localStorage.getItem('user')) {
                state.user = JSON.parse(localStorage.getItem('user'))
            }
        }
    

    And it works just fine, I'm wondering if I could put the router after the store and that hook to refresh and still be on the protected page, if somebody knows then great if not that'll be the matter of a further search/test :)