Search code examples
javascriptvue.jsvuejs2vuexvue-router

Vuex State returning values differently


I have a system where I am authenticating and storing user data in Vuex and then validating which views to show or not. I have a property named LoggedIn which is simply a boolean to check if user is logged in or not. let me show you the Vuex parts first

Actions.js

async login({ commit }, loginData) {
    const email = loginData.user.email;
      try {
        commit(USER_REQUEST_START);
        const response = await apolloClient.mutate({
          mutation: loginAccount,
          variables: { email: email },
        });

        router.push({ name: "Dashboard" });

        commit(SET_USER, response.data);

        Vue.prototype.$snotify.success("Login Successfully", {
          showProgressBar: true,
          timeout: 2000,
        });
      } catch (error) {
        commit(USER_REQUEST_ERROR, error);
        Vue.prototype.$snotify.error(error.message || "Some thing went wrong", {
          showProgressBar: true,
          timeout: 2000,
        });
      }

},

mutations.js

import defaultState from './state'

const mutations = {
  SET_USER(state, value) {
    state.data = value
    state.loggedIn = true
    state.loading = false
  },
}

export default mutations

login.vue

async submitForm() {
      try {
        const data = await this.$firebase
          .auth()
          .signInWithEmailAndPassword(this.email, this.password)
        const idTokenResult = await data.user
          .getIdTokenResult()
          .then((data) => data)

        const authTime = idTokenResult.claims.auth_time * 1000
        const sessionDuration = this.getSessionDuraion(
          authTime,
          SESSION_EXPIRE_DAYS,
        )
        const millisecondsUntilExpiration =
          new Date(sessionDuration).getTime() - authTime
        this.$store.dispatch('setUserSession', sessionDuration)
        setTimeout(() => {
          this.$firebase.auth().signOut()
        }, millisecondsUntilExpiration)
        this.$store.dispatch('login', data)
      } catch (error) {
        this.$snotify.error(
          (error && error.message) || 'Some thing went wrong',
          {
            showProgressBar: true,
            timeout: 2000,
          },
        )
      }
    },

this login method validates user sets User State in Vuex and should redirect to dashboard(this is the problem) there is where the below vuejs router action is called

router.js

router.beforeEach((to, from, next) => {
  const isAuthenticated = store.state.user.loggedIn
  const requiresAuth = to.matched.some((record) => record.meta.requiresAuth)
  console.log(store.state.user);
  console.log(store.state.user.loggedIn);
  if (requiresAuth && !isAuthenticated) {
    next({name: 'Login'})
  } else {
    if (store.state.user.sessionTimeOut && !store.getters.isSessionValid) {
      sessionMixin.methods.clearSessionStorage()
      next({name: 'Login'})
    } else {
      next(true)
    }
  }
})

this is where I am running into a problem, router.beforeEach is simply used to logged out if not authenticated and other processes. Now when i login the user set the state there is no error though, but a very wierd issue, the condition isAuthenticated doesnot work and when i try to console log it it returns false the funny part is when I console.log the actual object i do get the correct value please see the below image for more clarification enter image description here

extremely Odd behavior dont know whats the reason for doing this, can anyone help me out?


Solution

  • You are redirecting to the dashboard before setting the user, which will trigger the loggedIn check before it's ready.

    router.push({ name: "Dashboard" });
    commit(SET_USER, response.data);
    

    As for the console behavior, when logging an object or array to the console, when you click to expand/view the properties, the console shows you the properties as they are at the time of the click, not the time of the log. This is possible because JavaScript objects and arrays are references, so the console is able to update the display by reference.

    Here's an illustrative demo of that in action.

    (Converted from my comment as requested.)