Valary o
Valary o

Reputation: 577

How to access vuex getters from vue-router and set guards?

I am trying to get into the way of things with Vue but I've got some troubles with:

1: I cannot get access to my getters from router/index.js file. (I can get access to it but it return like a function with returns function with I cannot call and get the value)

2: I cannot set up guard properly. With Angular it's much easier

What am I doing wrong here? Any suggestions?

Router code

/* eslint-disable no-undef */
import Vue from "vue";
import VueRouter from "vue-router";
// import auth from '../store/modules/auth';
import { createNamespacedHelpers } from "vuex";
const { mapGetters } = createNamespacedHelpers("auth");
// import store from '../store';


Vue.use(VueRouter);

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("../components/Home.vue"),
    meta: { requiresAuth: true }
  },
  {
    path: "/users",
    name: "Users",
    component: () => import("../components/Users/Users.vue"),
    meta: { requiresAuth: true }
  },
  {
    path: "/sign-in",
    name: "SignIn",
    component: () => import("../components/SignIn/SignIn.vue"),
  }
];

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

router.beforeEach((to, from, next) => {
  const storeGetters = { ...mapGetters(['isAuthenticated', 'authStatus', 'test']) };

  const isUserLoggedIn = storeGetters.isAuthenticated;

  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (isUserLoggedIn) {
      console.log('user is authenticated');
      to; from;
      return next();
    } else {
      console.log('Access denied!');
      next({
        path: '/signIn',
        query: { redirect: to.fullPath }
      });
    }

    next({
      path: '/signIn',
      query: { redirect: to.fullPath }
    });

  } else {
    next();
  }

})

export default router;

Vuex index

import Vue from "vue";
import Vuex from "vuex";
import modules from "./modules"

Vue.use(Vuex);

export default new Vuex.Store({
  strict: true,
  modules,
  state: {
    testState: 'State value'
  },
  getters: {
    test: state => state
  }
});

auth module (vuex)

import { apolloClient } from '@/vue-apollo';
import SignInGQL from "@/graphql/signIn.gql";

export default {
    namespaced: true,
    state: {
        token: null,
        authStatus: false
    },
    getters: {
        isAuthenticated: (state) => {
            console.log('state: ', state);
            return !!state.token;
        },
        authStatus: state => state.authStatus,
        test: state => state.authStatus
    },
    actions: {
        async signIn({ commit, dispatch }, formInput) {

            try {
                const { data } = await apolloClient.mutate({
                    mutation: SignInGQL,
                    variables: { ...formInput }
                })

                const { token } = data.signIn;
                await commit('setToken', token);
                localStorage.setItem('auth-token', token);
                await dispatch('setUser', token);
            } catch (e) {
                console.error(e)
            }
        },
        async setUser({ commit }, token) {
            const encodedPayload = token.split('.')[1];

            const { payload } = JSON.parse(atob(encodedPayload));

            // TODO: Set User information 
            await commit('signInUser', payload);
        }
    },
    mutations: {
        setToken(state, token) {
            state.token = token
        },
        signInUser(state, user) {
            console.log('authStatus: ', state.authStatus)
            state.authStatus = true
            state.user = { ...user }
            console.log('authStatus: ', state.authStatus)
        },
        logOutUser(state) {
            console.log('dispatched logOutUser')
            state.authStatus = ''
            state.token = '' && localStorage.removeItem('auth-token')
        }
    }
}

Upvotes: 8

Views: 9594

Answers (2)

I faced the same problem...

Every time I tried to retrieve the getter's data inside the router it returned the function itself instead of the desired function's return value.

The solution:

In my code I used to call the createStore method inside the main.js file, but in order to be able to call the store's getters inside the vue-router you need to refactor your code, calling createStore in the same index.js file you declared it:

Before refactoring:

main.js file...

import store from './modules/index.js'
import { createStore } from 'vuex';
const mainStore = createStore(store)
app.use(store)

index.js file (Vuex store)...

const store = { ... store code here ... }
export default store

After refactoring:

main.js file...

import store from './modules/index.js'
app.use(store)

index.js file (Vuex store)...

import { createStore } from 'vuex'; 
const store = createStore({ ... store code here ... })
export default store

Upvotes: 1

Dan
Dan

Reputation: 63139

It seems createNamespacedHelpers is just complicating things. Import the store:

import store from '@/store'; // <-- aliased path

Use the getters like this:

const isAuthenticated = store.getters['auth/isAuthenticated'];
const authStatus = store.getters['auth/authStatus'];
const test = store.getters['auth/test'];

The first portion of the string is the Vuex module name, followed by the getter name.

Not only is this simpler to use, it's more readable and clear which module the getter comes from when studying the code.

Upvotes: 9

Related Questions