Vuex mapstate object undefined and "[vuex] unknown mutation type: " - vue.js

I'm new with vue.js and vuex and I've an issue with the mapstate object, first I've only one module in my store:
-Store
-index.js
-mutations.js
-actions.js
-state.js
state.js :
export default {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
So when I try to access the userInfo object everything works correctly:
computed: {
...mapState(["userInfo"]),
}
Then I decided to create modules:
-Store
-modules
-ldap.js
-commons.js
-index.js
So the userInfo is in the commons.js file and now when I try to get the object I always get undefined:
commons.js
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
actions,
mutations,
state
}
Component.vue
computed: {
...mapState(["userInfo"]), // <---- undefined
}
main.js :
import Vue from 'vue'
import Vuex from 'vuex'
import commons from './commons'
import ldap from './modules/ldap'
Vue.use(Vuex)
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Can you tell me how to access the userInfo object?
Thanks.

Considering:
Your commons.js is as follows:
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
namespaced: true, // <== make sure this is defined
actions,
mutations,
state
}
And main.js imports it like:
import commons from './commons'
// ..
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Then update on Component.vue:
import { mapState } from 'vuex'
// ...
computed: {
...mapState('commons', ["userInfo"]), // <== add module name here
}
Or
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('commons')
// ... notice module name above ^^^^^^^^^
computed: {
...mapState(["userInfo"]),
}
"[vuex] unknown mutation type: "
Since you are now namespacing your commons module, that modules' mutations now must be prefixed.
So, say you had a mutation like:
const mutations = {
changeName(state, data) {
state.name = data;
}
}
export default {
namespaced: true,
actions,
mutations,
state
}
And you used it like:
this.$store.commit('changeName', "New Name");
Now use it like:
this.$store.commit('commons/changeName', "New Name");

I guess you have namspaced your modules by adding namespaced: true in your module.
So you should pass the module name as the first argument to the mapState helpers so that all bindings are done using that module as the context. See Binding Helpers with Namespace
computed: {
...mapState('commons' , ["userInfo"])
}

You have to define each module as a individual store, here some pseudo example.
// authStore.js
import mutations from './authMutations'
import actions from './authActions'
import getters from './authGetters'
const initialState = {
...
}
export default {
state: initialState,
mutations,
actions,
getters
}
Then, register the modules
import authStore from './authStore'
const store = new Vuex.Store({
modules: {
{...authStore, namespaced: true},
{...postStore, namespaced: true} // some other module defined like auth
}
})
new Vue({
....
store: store
})
And then, on the component use it:
import { createNamespacedHelpers } from 'vuex'
// map state and actions of the module
const { mapState, mapActions } = createNamespacedHelpers('auth')
export default {
computed: {
...mapState({
prop1: 'prop1'
})
}
}
Vuex modules docs

It is really unclear in the documentation but namespaced: true is required to use the map functions.
At least as of the last comment in this discussion
https://github.com/vuejs/vuex/issues/855

Without the need to namespace your modules you can use the callback variant of mapstate:
computed: {
...mapState({
userInfo: state => state.commons.userInfo,
}),
},

Related

Vuex store is inaccessible

I made a vuex store:
export const general = {
namespaced: true,
state: {
menuEnabled: true,
headerEnabled: true
},
getters: {
menuState: state => state.menuEnabled,
headerState: state => state.headerEnabled
},
actions: {
setMenuVisibility({commit}, visibility) {
commit('setMenuVisibility', visibility);
},
setHeaderVisibility({commit}, visibility) {
commit('setHeaderVisibility', visibility);
}
},
mutations: {
setMenuVisibility(state, visibility){
state.menuEnabled = visibility;
},
setHeaderVisibility(state, visibility){
state.headerEnabled = visibility;
}
}
}
index.js
import { createStore } from "vuex";
import { auth } from "./auth.module";
import {general} from "./general.module";
const store = createStore({
modules: {
general,
auth
},
});
export default store;
main.js
import router from "./router";
import store from "./store";
createApp(App)
.use(store)
.use(router)
.mount('#app')
After that, I created 2 computed functions in App.vue:
computed: {
menuVisibilityState : function (){
return this.$store.state.menuEnabled;
},
headersVisibilityState : function () {
return this.$store.state.headerEnabled;
}
}
But, I can't get them from vuex:
I tried to import general directly in App.vue and get the values.
It doesn't work and I think, that it's bad way to get them.
Can somebody help me?
When you create a module in Vuex, the local state is nested depending on the name you've provided to the module (this happens when you're accessing the root state.).
In your example, to access the local state of general module you could write:
computed: {
menuVisibilityState : function (){
return this.$store.state.general.menuEnabled;
},
headersVisibilityState : function () {
return this.$store.state.general.headerEnabled;
}
}
Keep in mind that:
actions and mutations are still registered under the global namespace - this allows multiple modules to react to the same action/mutation type. Getters are also registered in the global namespace by default.
https://vuex.vuejs.org/guide/modules.html#namespacing

How do I access my state object in store from module?

I need a data from my store object above in my module, but I cannot access it.
I have a store object
This store object has one or more modules it uses.
I was try it :index.js
import { createStore } from "vuex";
import moduleLayout from "./modules/moduleLayout.js"
export default createStore({
state:{
testData:'Hello World!'
},
modules: { moduleLayout }
})
and have a moduleLayout.js
export default {
state:{
size:100
},
getters:{
getSizeAndText:(state)=>{
return {size:state.size,text:this.state.testData};
//error here, because (this)undefined
//how can i access on here testData
}
}
}
I cannot access testData data from my moduleLayout.js
No need to import index.js.
We can access it by expanding the parameter field.
on "index.js"
import moduleTest from "./modules/moduleTest";
export default{
state:{
size:100
},
modules:{
moduleTest:moduleTest
}
}
on "moduleTest.js"
export default{
state:{
testSize:20
},
getters: {
getSumSize(thisState, getters, state) {
return thisState.testSize+state.size;//this result 120
},
getSumSizeWithParam:(thisState, getters, state) =>(index)=>{
return (thisState.testSize+state.size)*index;//this result 120*index
}
}
}
You definitely don't need to import index.js.
You are not adding the module to the store.
import { createStore } from "vuex";
import moduleLayout from "./modules/moduleLayout.js";
export default createStore({
state: {
testData: 'Hello World!'
},
modules: {
layout: moduleLayout
}
})
Import the store inside module to access the state thats not namespaced by module:
import store from '../index.js'; // whatever the path of where you create and export store
const state = {
size: 100
}
const getters = {
getSizeAndText(state) {
return {
size: state.size,
text: store.state.testData
}
}
}
export default {
state,
getters
}

Vue x module Namespace

I'm stuck on a problem that I had already encountered and which was resolved with the namespaced but nothing helped.
This is my module:
const Algo1Module = {
namespaced: true,
state: {
questions: {
question1: "test",
question2: "",
question3: "",
question4: "",
question5: "",
question6: ""
}
},
getters: {
getMyQuestions(state) {
return state.questions;
}
}
};
export default Algo1Module; // export the module
This is my index.js from my store:
import Vuex from "vuex";
import createLogger from "vuex/dist/logger";
import algo1 from "#/store/modules/algo1.store";
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== "production";
export default new Vuex.Store({
modules: {
algo1
},
strict: debug,
plugins: debug ? [createLogger()] : []
});
And i try to access to my getters from my component like this :
<script>
import { mapGetters } from "vuex";
export default {
name: "Algo",
computed: {
...mapGetters("Algo1Module", ["getMyQuestions"])
}
};
</script>
But i have an error message in console : [vuex] module namespace not found in mapGetters(): Algo1Module/
I don't understand or I may have made a mistake.
Thank you for the answer you can give me.
It will take name that you set up when imported module, try algo1
Your module name is registered under algo1 name.
If you want to call it Algo1Module then register it in the store like that:
modules: {
Algo1Module: algo1,
}

How to use non-namespaced and namespaces modules at the same time in Vuex

I'm trying to have a state that consists of namespaced modules and a global state. Unfortunately, I can access the global actions but I can't get the global state properties.
If I try to use mapState in a component like this,
computed: {
...mapState(['editMode']),
...mapState('address', ['addresses']),
}
I have access to addresses, but editMode is always undefined. Mapping actions works flawlessly and updates the state according to the Vuex Chrome Tool.
But I noticed, that the global state is shown under its own "namespace" "global". So I tried to map using ...mapState('global', ['editMode']), but got an error that the namespace does not exist.
Here's my code:
index.ts
import Vue from 'vue';
import Vuex from 'vuex';
import address from './modules/address';
import global from './global';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
address,
global,
},
});
modules/address.ts
export default {
namespaced: true,
state: {
addresses: [],
},
mutations: {
...
},
actions: {
...
},
};
global.ts
export default {
namespaced: false,
state: {
editMode: 0,
},
mutations: {
SET_EDIT_MODE(state, value) {
state.editMode = value;
},
},
actions: {
setEditMode({ commit }, editMode) {
commit('SET_EDIT_MODE', editMode);
},
},
};
State is not affected by namespace. In a way it always gets namespaced. This is so we don't have collision.
To access a state from a module you need to get a bit verbose:
computed: {
...mapState({
editMode: state => state.global.editMode
}),
...mapState('address', ['addresses']),
}

Unable to call vuex namespaced module action from Vue component

I have a Vue component that uses Vuex with namespaced modules.
// Main Component
import store from './store';
import {mapState, mapGetters, mapActions} from 'vuex';
new Vue({
store,
computed: {
...mapState({
showModal: state => state.showModal,
}),
computed: {
...mapState('ModuleA', {
a: state => state.a,
}),
...mapState('ModuleB', {
b: state => state.b,
}),
...mapGetters('ModuleA', { getA: 'getA' } ),
...mapGetters('ModuleB', { getB: 'getB' } ),
},
methods: {
...mapActions('ModuleA', [ 'doSomeA']),
...mapActions('ModuleB', [ 'doSomeB']),
},
mounted() {
let payLoad = { ... },
this.doSomeA(payload); // I never see this getting dispatched
}
// Store
export default new Vuex.Store({
modules: { ModuleA, ModuleB }
...
}
// Module A
export default {
namespaced: true,
actions: {
doSomeA: ({dispatch, commit, getters, rootGetters}) => payload => { // do something with payload }
...
}
Since I have mapped the action from my namespaced module I am simply calling the action like normal method in my component. But somehow its not dispatching the action. Any idea what is going wrong here?