Laravel + Vuejs have trouble with async problem

Viewed 531

I have a async problem with my Vuejs/Laravel App.

If a user is connected i have in vuex : my state user and a state token. I set this token in the localStorage and with that i can relogin him if my user F5 (refresh page).

There is my store (namespaced:auth) :

export default {
    namespaced: true,
    state: {
        token: null,
        user: null
    },
    getters: {
        authenticated(state){
            return state.token && state.user;
        },
        user(state){
            return state.user;
        }
    },
    mutations: {
        SET_TOKEN(state, token){
            state.token = token;
        },
        SET_USER(state, data){
            state.user = data;
        },
    },
    actions: {
        async login({ dispatch }, credentials){
           let response = await axios.post(`/api/auth/connexion`, credentials);

           dispatch('attempt', response.data.token);
        }
        , 
        async attempt({ commit, state }, token) {
            if(token){
                commit('SET_TOKEN', token);
            }
            if (!state.token){
                return
            }
            try{
                let response = await axios.get(`/api/auth/me`);
                commit('SET_USER', response.data);
                console.log('Done')
            }
            catch(err){
                commit('SET_TOKEN', null);
                commit('SET_USER', null);
            }
        }
    }
}

My app.js, i do that for relog my current user :

store.dispatch('auth/attempt', localStorage.getItem('token'));

And for finish on route in router :

{
    name: 'Login',
    path: '/',
    component: Login,
    beforeEnter: (to, from, next) => {
      console.log('Getter in router : ' + store.getters['auth/authenticated']);
      if (!store.getters['auth/authenticated']){
        next()
      }else {
        return next({
          name: 'Home'
        })
      }
    }
  }

Where is the problem, if i call in a Home.vue my getter "authenticated" is work fine (true if user connect and false if not).

But in my router is take all time default value set in store (null). I know why is because if i reload my page for 0.5s the store state is null and after that the localStorage is learn and my user and token is created.

What i want (i think) is the router wait my actions attempt and after that he can do check.

I have follow a tutoriel https://www.youtube.com/watch?v=1YGWP-mj6nQ&list=PLfdtiltiRHWF1jqLcNO_2jWJXj9RuSDvY&index=6

And i really don't know what i need to do for my router work fine =(

Thanks a lot if someone can explain me that !

Update :

If i do that is work :

{
    name: 'Login',
    path: '/',
    component: Login,
     beforeEnter:async (to, from, next) => {
      await store.dispatch('auth/attempt', localStorage.getItem('token'));

      if (!store.getters['auth/authenticated']){
        next()
      }else {
        return next({
          name: 'Home'
        })
      }
    }

But i want to understand what i really need to do because that is not a clear way is really trash.

Update2:

Maybe i found the best solution if someone have other way i take it.

{
    name: 'Home',
    path: '/accueil',
    component: Home,
    beforeEnter: (to, from, next) => {
      store.dispatch('auth/attempt', localStorage.getItem('token')).then((response) => {
        if (!store.getters['auth/authenticated']){
          return next({
            name: 'Login'
          })
        }else {
          next();
        }
      });
    }
  }
1 Answers

I answer more clearly how easily wait the store !

Before in my app.js i have this :

store.dispatch('auth/attempt', localStorage.getItem('token'));

Is set for normaly every reload do that but if i put a console.log in, i see the router is execute and after the action 'attempt' is execute.

So delete this line in app.js and you can add a .then() after !

router.beforeEach((to, from, next) => {
  store.dispatch('auth/attempt', localStorage.getItem('token')).then(() =>{
    if (store.getters['auth/authenticated']){
      next();
    }else {
      //something other
    }
  })
})

With that i have the same line code but i can say wait action "attempt" to my router.

I'm not sur is the best way obviously. But is work and i think is not a bad way !

Related