Mutation Doesn't Set Value in State - vue.js

I set values with mutations, but it doesn't update values in state object. It creates new variables inside mutations object.
mutations.js:
const mutations = {
setUser(state, user) {
state.user = user; // eslint-disable-line no-param-reassign
},
setToken(state, token) {
state.token = token; // eslint-disable-line no-param-reassign
},
setAuthenticated(state, authenticated) {
state.authenticated = authenticated; // eslint-disable-line
},
};
export default {
mutations,
};
state.js:
const state = {
callingAPI: false,
activeSidebar: true,
searching: '',
authenticated: null,
user: null,
token: null,
userInfo: {
messages: [],
notifications: [],
tasks: [],
},
};
const getters = {
isAuthenticated: (state) => { // eslint-disable-line
return state.authenticated;
},
isActiveSidebar: (state) => { // eslint-disable-line
return state.activeSidebar;
},
};
export default {
state,
getters,
};
store.js:
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import mutations from './mutations';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
state,
mutations,
},
});
I update a value with commit function. e.g.: this.store.commit('setAuthenticated', true);
import { mapMutations } from 'vuex';
import store from '../store';
export default {
computed: {
...mapMutations([
'setAuthenticated',
'setUser',
'setToken',
]),
},
store,
login(context, creds) {
context.$http.post(LOGIN_URL, JSON.stringify(creds)).then(
(response) => {
if (response.status === 200) {
const bodyText = response.bodyText.split('\n');
const token = bodyText[0].split(' ');
let redirect = bodyText[1];
redirect = redirect.substring(redirect.indexOf('[') + 1, redirect.indexOf(']'));
this.store.commit('setToken', token[1]);
this.store.commit('setAuthenticated', true);
...........
});
}
Isn't it supposed to update null values in state object instead of creating new variables in mutations object?

You seem to be misusing modules. I'll assume you aren't actually trying to use them. You also have unintended property nesting with your state import.
store.js
import Vue from 'vue';
import Vuex from 'vuex';
import {state,getters} from './state';
import mutations from './mutations';
Vue.use(Vuex);
export default new Vuex.Store({
state,
getters,
mutations,
});

Related

i have Error : unknown action type: addUserAction

I'm having a problem which is it gives me an error " [vuex] unknown action type: addUserAction " when I dispatch Action :-
here's my module called " HomePage "
import axios from 'axios'
export default {
state : () => ({
categories : [],
users : []
}),
mutations :{
GET_CATEGORIES( state ,categories){
state.categories = categories
},
ADD_USER(state , user){
state.users.push(user)
}
},
actions :{
getEcommCategories({commit}){
return axios.get("/api/ecommerceCategories").then(res =>{
commit('GET_CATEGORIES' , res.data.data) ;
})
},
addUserAction({commit},user){
return commit('ADD_USER' , user)
}
}
}
and this is my store :-
import Vue from "vue";
import Vuex from "vuex"
import * as HomePage from "./HomePage/home"
Vue.use(Vuex)
export default new Vuex.Store({
modules :{
HomePage
},
state,
getters,
actions,
mutations,
})
so I try to dispatch action in methods like this
add(){
this.$store.dispatch('addUserAction', this.user)
},
I think changing import * as HomePage from "./HomePage/home" to import HomePage from "./HomePage/home" in your store file might work.
Hope this helps.
add namespaced: true to your module like this:
module:
export default {
namespaced: true,
state,
getters,
actions,
mutations,
};
root:
import customNamespace from ./customNamespace.js
modules: {
customNamespace
}
component:
this.$store.dispatch('customNamespace/action', payload)
I personally like to define everything in constants:
const NAMESPACE = 'selectOption';
const GET_SELECT_OPTIONS = 'selectOptions';
const INITIALIZE_SELECT_OPTIONS = 'initializeSelectOptions';
export const GETTER_SELECT_OPTIONS = `${NAMESPACE}/${GET_SELECT_OPTIONS}`;
export const ACTION_INITIALIZE_SELECT_OPTIONS = `${NAMESPACE}/${INITIALIZE_SELECT_OPTIONS}`;
const state = {
selectOptions: [],
};
const getters = {
[GET_SELECT_OPTIONS]: (state) => state.selectOptions,
}
const actions = {
async [INITIALIZE_SELECT_OPTIONS](context, payload) {
...
}
}
const mutations = {
...
}
export default {
namespaced: true,
state,
getters,
actions,
mutations,
};
and then in my component i can use the action like this:
this.$store.dispatch(ACTION_INITIALIZE_SELECT_OPTIONS, payload)
or use mapActions by vuex:
methods: {
...mapActions({ initializeSelectOptions, ACTION_INITIALIZE_SELECT_OPTIONS}),
async myMethod(){
await this.initializeSelectOptions(this.payload)
}
}

Vuejs with namespaced modules and unknow mutation type

i have created two store modules and I did the import into main store.
When I load my drawer view, I am getting the next error.
What am I doing wrong here
error:vuex.esm.js [vuex] unknown mutation type: SET_DRAWER
//Drawer.vue
.........
computed: {
...mapState("navstore", ["barColor", "barImage"]),
drawer: {
get() {
return this.$store.state.navstore.drawer;
},
set(val) {
this.$store.commit("SET_DRAWER", val);
},
},
computedItems() {
return null;
//this.items.map(this.mapItem);
},
profile() {
return {
avatar: true,
title: "Gestan",
};
},
},
methods: {},
.........
.........
//store/index.js
import Vue from "vue";
import Vuex from "vuex";
import { default as auth } from ".auth";
import { default as navstore } from "./navStore";
Vue.use(Vuex);
export default new Vuex.Store({
modules: { auth: auth, navstore: navstore },
});
//navstore.js
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
export default {
namespaced: true,
state: {
barColor: "rgba(0, 0, 0, .8), rgba(0, 0, 0, .8)",
barImage:
"https://demos.creative-tim.com/material-dashboard/assets/img/sidebar-1.jpg",
drawer: null,
},
mutations: {
[SET_BAR_IMAGE](state, payload) {
state.barImage = payload;
},
[SET_DRAWER](state, payload) {
state.drawer = payload;
},
},
actions: {
actionSetDrawer({ commit }, payload) {
commit(SET_DRAWER, payload);
},
},
};
//auth.js
import Vue from "vue";
import Vuex from "vuex";
import * as storage from "#/store/storage";
import services from "#/services/api/AuthenticationService";
Vue.use(Vuex);
const SET_USER = "AUTH/SET_USER";
const SET_TOKEN = "AUTH/SET_TOKEN";
export default {
namespaced: true,
state: {
token: null,
user: null,
isUserLoggedIn: false,
},
mutations: {
[SET_TOKEN](state, token) {
state.token = token;
state.isUserLoggedIn = !!token;
},
[SET_USER](state, user) {
state.user = user;
},
},
getters: {
isAuthenticated: (state) => !!state.token,
// authStatus: state => state.status
},
actions: {
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
};
You need to remove prefixes with slash from mutation names because your modules namespaced and you will always access this mutations outside indicating a module name like this moduleName/mutation.
For instance:
const SET_BAR_IMAGE = "NAVSTORE/SET_BAR_IMAGE";
const SET_DRAWER = "NAVSTORE/SET_DRAWER";
// should be
const SET_BAR_IMAGE = "SET_BAR_IMAGE";
const SET_DRAWER = "SET_DRAWER";
Because the SET_DRAWER mutation is inside a navspaces module you should call it indicating a module name:
this.$store.commit("navstore/SET_DRAWER", val);
Don't try to call actions inside actions like this:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
dispatch("actionSetUser", res.data.user);
dispatch("actionSetToken", res.data.token);
});
},
Use mutations in a desired combination:
actionDoLogin({ dispatch }, payload) {
return services.login(payload).then((res) => {
commit(SET_USER, res.data.user);
commit(SET_TOKEN, res.data.token);
});
},

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')
}
}
}
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.
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

vuex store state update value in middleware check-auth.js, but can't get the updated value in vue view

I am using nuxtjs for myProject, i useing axios to get auth information in minddleware/check-auth.js and commit the flag to store.state.isSEPCNavFlag;
But i can't get the updated isSEPCNavFlag value in vue view, the value is always null.
anyone can help me? please...
store/index.js
import axios from 'axios'
import echarts from 'echarts'
import Vue from 'vue'
import Vuex from 'vuex'
import { saveToken, delToken } from '#/utils/auth'
Vue.use(Vuex)
export const strict = true
export const state = () => ({
authUser: null,
user: '',
locale: null,
locales: ['zh', 'en'],
isMenuHidden: true,
isSEPCNavFlag:null,
})
export const mutations = {
SET_SEPCFLAG: function (state, isSEPCNavFlag) {
state.isSEPCNavFlag = isSEPCNavFlag
},
SET_TOKEN: function (state, token) {
state.authUser = token
},
SET_USER: function (state, user) {
state.user = user
},
SET_MENUS: function (state, menus) {
state.menus = menus
},
SET_LANG (state, locale) {
if (state.locales.indexOf(locale) !== -1) {
state.locale = locale
}
},
TOGGLE_MENU_HIDDEN: function (state) {
state.isMenuHidden = !state.isMenuHidden
}
}
minddleware/check-auth.js
async function toNavTO(token,store) {
var returnData = await funcAsync(token)
var ACNameIndex = returnData.data.indexOf("<AccountName>");
var navFlag = true;
if(ACNameIndex == -1){
navFlag=false
}
store.commit('SET_SEPCFLAG', navFlag)
}
index.vue
mounted(){
this.login();
},
methods: {
login(){
let navFlag = this.$store.state.isSEPCNavFlag;
console.log(navFlag);
this.$store.state.isSEPCNavFlag value always null.
mutations SET_SEPCFLAG console.log

vuex dynamic module register shows object empty

I have registered vuex module with this function this.$store.registerModule(this.name, 'some_module') module created but showing empty in vuedevtools.
and I'm trying to dispatch with this code this.$store.dispatch(this.name+'/some_action', this.id)this return error unknown action type
please help anyone how to create vuex module dynamically.
store index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// Load store modules dynamically.
const requireContext = require.context('./modules', false, /.*\.js$/)
const modules = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)]
)
.reduce((modules, [name, module]) => {
if (module.namespaced === undefined) {
module.namespaced = true
}
return { ...modules, [name]: module }
}, {})
export default new Vuex.Store({
modules
})
somo_module.js
import Vue from 'vue'
import axios from 'axios'
import * as types from '../mutation-types'
// state
export const state = {
count: ''
}
// getters
export const getters = {
count: state => state.count
}
// mutations
export const mutations = {
[types.GET_COUNT] (state, data ) {
state.count = data
}
}
// actions
export const actions = {
async some_action ({ commit }, payload) {
try {
const { data } = await axios.post('/count/'+payload)
commit(types.GET_COUNT, data )
// console.log(data)
} catch (e) {
}
}
}
First you have to make sure that this.name !== undefined then you can dynamically add the module to the store like this (according to the DOC and API Reference)
this.$store.registerModule(this.name, {
namespaced: true,
state: {
some_items: []
},
getters: {
items: state => state.some_items
},
actions: {
someAction () {}
},
mutations: {}
})
And use it as you always do this.$store.dispatch('yourModule/someAction')
If you wish you can also update your store index.js like this in order to register modules that have been exported by default as object
myModule.js
const state = {}
const actions = {}
const getters = {}
const mutations = {}
const module = {
namespaced: true,
state,
getters,
mutations,
actions
}
export default module
store index.js
As you can see below i only made a small changes to the reduce method
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// Load store modules dynamically.
const requireContext = require.context('./modules', false, /.*\.js$/)
const modules = requireContext.keys()
.map(file =>
[file.replace(/(^.\/)|(\.js$)/g, ''), requireContext(file)]
)
.reduce((modules, [name, mod]) => {
let module = mod.default || mod
if (module.namespaced === undefined) {
module.namespaced = true
}
return { ...modules, [name]: module }
}, {})
export default new Vuex.Store({
modules
})