19
votes

I am using VueJS in conjunction with vuex and vue-router. I have a vuex module that is making a mutation to its store, and trying to use that to determine whether or not a user is authenticated.

Here is what my code looks like in relevant part.

main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'
import router from './router'

router.beforeEach((to, from, next) => {
    console.log(router.app) // prints a Vue$2 object
    console.log(router.app.$store) // undefined
    console.log(store.getters.isAuthenticated) // false
    ...
}

const app = new Vue({
  store,
  router,
  ...App
})

app.$mount('#app')

/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import core from './modules/core'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    core: core
  }
})

export default store

/store/modules/core.js

import * as types from '../types'
import api from '../../api'
import router from '../../router'

const state = {
  token: null,
  user: null,
  authenticated: false
}

const mutations = {
  [types.LOGIN_SUCCESS] (state, payload) {
    console.log('mutate')
    state.token = payload.token
    state.user = payload.user
    state.authenticated = true
    router.go('/')
  }
}

const getters = {
  isAuthenticated: state => {
    return state.authenticated
  }
}

const actions = {
  [types.LOGIN] (context, payload) {
    api.getToken(payload).then(response => {
      context.commit(types.LOGIN_SUCCESS, response)
    })
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

When I go thru my logic to trigger the LOGIN action, I can see that the mutation executed properly, and when I use the Chrome extension to view the vuex state for my core module, the state for user and authenticated have been properly mutated.

QUESTION

It seems like this module just simply has not been loaded by the time the router is running in the .beforeEach loop. Is this true?

If yes, what are some other suggestions on how to handle this situation? If no, what am I doing incorrect?

1
what do you get if you log store.state.core.authenticated?François Romain
@francoisromain console.log(store.state.core.authenticated) returns falseThe Brewmaster
I THINK I figured out the problem. But, until I do a little more research ... I will not post my own answer. It seems like the state is not persistent and is not making use of something like HTML5 localstorage. Therefore, on each page load, the state is empty. So, I need to move my user into localstorage (or some equivalent) to get that sort of persistence. I have a workable solution, and will post it when I am more certain that this is the best method.The Brewmaster
@TheBrewmaster maybe this can help.. github.com/Ridermansb/vuex-router-auth0-exampleridermansb

1 Answers

5
votes

console.log(store.state.core.authenticated) return false because you not make a login yet.

In your code you not persist user info in anywhere. E.g. using localstorage

Same considerations:

  1. Not use router.app.$store, use store that you import
  2. In your LOGIN_SUCCESS mutation, store login info and token into localstorage
  3. In your beforeEach hook, check localstorage, if was populated with token, get user information and apply the mutation. If not, just call login page

Something like this..

const mutations = {
  [types.LOGIN_SUCCESS] (state, payload) {
    state.token = payload.token
    state.user = payload.user
    state.authenticated = true
    localstorage.setItem('token', payload.token)
    localstorage.setItem('user', payload.user)
  }
}

const actions = {
  [types.LOGIN] (context, payload) {
    return api.getToken(payload).then(response => {
      context.commit(types.LOGIN_SUCCESS, response)
      return response
    })
  }
}

router.beforeEach((to, from, next) => {
    let user = localstorage.getItem('user')
    let token = localstorage.getItem('token')
    if (user && token) {
      store.commit(types.LOGIN_SUCCESS, {token, user})
      next()
    }
    else if (!store.getters.isAuthenticated) {
      store.dispatch(types.LOGIN).then(() => next())
    } else {
      next()
    }
}