Home > database >  What am I doing wrong when using Vuex.Store?
What am I doing wrong when using Vuex.Store?

Time:02-21

I want to take advantage of the "Vuex Store" capabilities to store and use the "isAuthenticated" variable throughout the project, in accordance with this, give access to routes. What is the my misstake? I spent a lot of time, reviewed a bunch of different ways to embed the vue store into the project, nothing came of it.

My "index.js" from "store":

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

const store = new Vuex.Store({
    state: {
        isAuth: false,
    },
    mutations: {
        setAuthStatus(state, status) {
            state.isAuth = status;
        },
    },
});
export default store;

My "main.js" from "root(src)":

import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import vuetify from './plugins/vuetify';

Vue.config.productionTip = false;

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

Browser error: enter image description here

CodePudding user response:

There are massive, let's say, holes in your shown code (or you have not included them). First of all, isAuth is just a boolean (true/false). You have to use it somewhere in order for this to work (ie, in the router.js file to prevent navigation to certain routes depending on the condition).

Below is a simple implementation of user authentication and roles. I admit, it is a bit more complicated then your example, but I think you will get the idea.

Router

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
import Home from "../views/Home.vue";
import store from "../store";

const routes: Array<RouteRecordRaw> = [
  {
    path: "/",
    name: "Home",
    component: Home,
  },
  {
    path: "/admin",
    name: "Admin",
    component: () => import("../views/Admin.vue"),
    children: [],
    meta: { role: "admin", requiresAuth: true },
  },
  {
    path: "/manager",
    name: "Manager",
    component: () => import("../views/Manager.vue"),
    children: [
      {
        path: "/employees",
        name: "Employees",
        component: () => import("../views/children/manager/Employees.vue"),
      },
    ],
    meta: { role: "manager", requiresAuth: true },
  },
  {
    path: "/employee",
    name: "Employee",
    component: () => import("../views/Employee.vue"),
    children: [],
    meta: { role: "employee", requiresAuth: true },
  },
  {
    path: "/login",
    name: "Login",
    component: () => import("../views/Login.vue"),
    meta: { requiresAuth: false },
  },
  {
    path: "/about",
    name: "About",
    component: () => import("../views/About.vue"),
    meta: { requiresAuth: false },
  },
];

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
});

router.beforeEach((to) => {
  if (to.meta.requiresAuth && !store.getters.isLoggedIn) {
    return { path: "login" };
  } else if (to.meta.role && to.meta.role !== store.getters.userRole) {
    return { path: store.getters.userRole };
  }
});

export default router;

Two items that are key here. The meta property on some of the routes and the beforeEach method that runs on every route change.

The meta property just tells the router, "Hi, these are my conditions, you must meet them before you can enter" (which we enforce in the beforeEach method with the checks).

Store

import { createStore } from "vuex";
import { User } from "../types";

export default createStore({
  state: {
    user: <User>{},
  },
  getters: {
    isLoggedIn: (state): boolean => !!Object.keys(state.user).length,
    userRole: (state): string => state.user.role,
  },
  mutations: {
    SET_USER(state, user): void {
      state.user = { ...user };
    },
  },
  actions: {},
  modules: {},
});

We are exporting this to the router.js file which is using the getters for the beforeEach method.

App

import { createApp } from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import router from "./router";
import store from "./store";

createApp(App).use(store).use(router).mount("#app");

The main file shouldn't have anything special inside of it.

Versions

Vuex 4.0 is compatible with Vue3, so make sure you are using Vue3 (based on your syntax it doesn't look like it).

CodePudding user response:

@EstusFlask , The vuex version is "vuex": "^4.0.2".

@yepsolutely. In that and a problem that I even do not cause a mutation. I'm just trying to connect it first. But in the future I use it during the login on the "/login" page.

enter code here
methods: {
        async login() {
            this.loading = true;
            await axios
                .post("https://myurl/auth/login", {
                    email: this.email,
                    password: this.password,
                })
                .then((res) => {
                    localStorage.setItem("token", res.data.token);
                    // this.$store.commit("setAuthStatus", true);
                    this.loading = false;
                });
        },
    },
  • Related