Vuex2.0 how to configure and how to getters - vue.js

Early today try vuex 2.1.2 vue:2.1.0, the directory structure is as follows
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import common from './common/store'
export default new Vuex.Store({
modules : {
common
}
})
mutations-types.js:
export const ADD_NUM = "ADD_NUM"
common/store.js:
import * as types from '../mutations-types'
const state = {
num : 1
}
const mutations = {
[types.ADD_NUM] : function(state){
state.num = state.num + 1;
},
}
export default {
state,
mutations
}
common/actions.js:
import * as types from '../mutations-types'
export default {
setNum : store => {
store.dispatch(types.ADD_NUM)
},
}
common/getters.js:
export default {
getNum : state => {
state.common.num
},
}
Then get the value of num in Hello.vue through getters
In the vue entry file main.js, a store is injected
run error:
Property or method "getNum" is not defined on the instance but
referenced during render
Why is this error reported? Does this directory structure and code correct?

First of all, I did not read the official documents
Using mapGetters solves the problem
THANKS #Potray
I refer to the official demo link

Related

vuex state not updating UI on change

I am in the process of converting a vue2 to vue3 project and noticed my UI isn't updating when objects from my vuex store are updating. Here is how I create my store:
store/index.js
import {mutations} from './mutations';
import {createStore} from 'vuex'
export default createStore({
state() {
return {
...
}
},
mutations
});
mutations.js
export const mutations = {
narrative(state, v) {
state.narrative = v;
}
};
app.js
import { createApp } from 'vue';
import store from './store/index';
const app = createApp({
mixins: [
require('./mixins/base')
]
}).use(store)
So when I mutate one of the vuex objects, I write to the console log immediately and see the data has changed
let narrative = _.find(this.$store.state.narratives, ['id', this.selectedNarrativeId]);
if (narrative) {
console.log(narrative.id); // PRINTS CORRECT UPDATED ID
this.$store.commit('narrative', narrative);
console.log(this.$store.state.narrative.id); // PRINTS CORRECT UPDATED ID
}
But the UI does not change. However, if I used a computed property, the UI updates immediately. What am I doing wrong with the vuex store?
computed: {
currentNarrative() {
let narrative = _.find(this.$store.state.narratives, ['id', this.selectedNarrativeId]);
if (narrative) {
return narrative;
}
return {};
},
}
Versions
vue 3.2.33
vuex 4.0.2
Replacing the require by an import + rebooting the machine fixed the issue, maybe some broken was still running on the server.

Cannot access state of vuex module

This is my first project with Vue and I am having some trouble accessing state of vuex module.
I am currently using quasar.
Here is my code calling the state.
mounted() {
console.log("Connected", this.$store.hasModule("module"));
console.log("Module: ", this.$store.state.module);
console.log("State: ", this.$store.state.module.count)
console.log("Map State: ", this.count);
},
computed: {
// look up in `some/nested/module`
...mapState({
count: state => state.module.count // Uses the state of the module
})
},
And here is the output I am getting
Console output
Connected true
OverviewPage.vue?1b50:26 Module: Object
OverviewPage.vue?1b50:27 State: undefined
OverviewPage.vue?1b50:28 Map State: undefined
Here are my vuex codes.
This is index of the base vuex(where vuex is put).
import Vue from "vue";
import Vuex from "vuex";
// import example from './module-example'
Vue.use(Vuex);
/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/
export default function(/* { ssrContext } */) {
const Store = new Vuex.Store({
modules: {
module: () => import("src/store/module-example/index.js")
},
// enable strict mode (adds overhead!)
// for dev mode only
strict: process.env.DEBUGGING
});
return Store;
}
This is the index inside my 'module' folder
import state from "./state";
import * as getters from "./getters";
import * as mutations from "./mutations";
import * as actions from "./actions";
export default {
namespaced: true,
getters,
mutations,
actions,
state
};
And this is my state file inside that module.
export default function() {
return {
count: 0
};
}
I have never used vuex before so, I am not really sure where I am getting this wrong.
If you have any solutions or advices for this, I would very much appreciate it! :)
Thanks ahead!

how to get access to vuex inside other js files like plugins in nuxt

i have a problem. i wanna get access to one of my getters inside my vee-validate.js file.
how can i do that?
in my pages and components, (in <script>...</script> part, outside export default{...}) i used this function:
component.vue
<script>
let lang;
function getLang({store}) {
lang = store.state.lang
}
export default{
...
}
but it is not working!
i'm trying to access my custom lang file (for translation purpose) that is stored in lang state in my vuex, and use it in vee-validate.js file for custom message.
i tried to import store but not working.
veevalidate.js:
import Vue from 'vue'
import { required } from 'vee-validate/dist/rules'
import { extend, ValidationObserver, ValidationProvider, setInteractionMode } from 'vee-validate'
import {store} from '../store'
let langFile = store
setInteractionMode('eager')
extend('required', {
...required,
message: ''
})
Vue.component('ValidationProvider', ValidationProvider);
Vue.component("ValidationObserver", ValidationObserver);
UPDATED: My store index.js
import langfile from '../static/lang'
export const state = () => ({
lang: null,
dir: null,
})
export const getters = {
//----------------- Language and Direction
lang(state){
return state.lang
},
dir(state){
return state.dir
},
}
export const mutations = {
SET_LANGUAGE(state, lang){
state.lang = lang
},
SET_DIRECTION(state, dir){
state.dir = dir
},
}
export const actions = {
async nuxtServerInit({dispatch, commit}) {
// ------------- Read Language File
let baseLang = process.env.SITE_LANGUAGE;
let siteLang = langfile[baseLang];
let siteDir = langfile[baseLang]['dir'];
commit('SET_LANGUAGE', siteLang);
commit('SET_DIRECTION', siteDir);
},
}

Correct syntax for multiple modules in vuex

Vue and vuex begginer. I am trying to set a single store with multiple modules in vuex.
The folder structure is
store (folder)
index.js
modules (folder)
hoodies.js
shoes.js
My index.js has
import Vue from 'vue'
import Vuex from 'vuex'
import hoodies from'./modules/hoodies';
import shoes from'./modules/shoes';
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
hoodies
,shoes
}
})
Inside hoodies.js and shoes.js I have the same structure, the difference is the word "shoes" or "hoodies"
import axios from 'axios'
const state = {
shoes:[]
};
const getters = {
allShoes : state => state.shoes
};
const actions = {
async fetchShoes({commit}){ //....
}
const mutations = {
setShoes:(state, shoes) => (state.shoes = shoes),
}
export default{
namespaced: true,
state,
getters,
actions,
mutations
};
I want to use shoes and hoodies in the same component. I am confused because I dont know if this is the correct syntax and a lot of tutorials do not explain how to do this.
So, I am trying like so.
import { mapGetters, mapActions } from 'vuex';
methods:{
...mapActions('./store/modules/shoes', [ 'fetchShoes' ]),
...mapActions('./store/modules/hoodies', [ 'fetchHoodies' ]),
comboboxChange(){
this.fetchHoodies();
}
},
created(){
this.fetchShoes();
}
I get no errors in the console. But the browser console says [vuex] module namespace not found in mapActions(): ./store/modules/shoes/
Please help me debug this, a simple solution goes a long way. I dont know what to do. Thanks
First problem I see is that you import your modules as "vessels" and "charts", so you need to register that names in module. I recommend to change your imports like this:
import Vue from 'vue'
import Vuex from 'vuex'
import hoodies from'./modules/hoodies';
import shoes from'./modules/shoes';
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
hoodies,
shoes
}
})
You don't need getters to return exact state values, you can reach state directly from component. Since you are using namespaced modules you get state value in component like this: this.$store.state.shoes.shoes
Getters you usually use when you need some computed value(s) from state.

How to use shorter path to get vuex contents?

In my vuex /store/state.js I have an export default that looks like this:
export default {
foo: {
bar:{
tar: {
info: 42
}
}
}
}
So, whenever I want to access info, I usually do in my methods like this;
methods: {
getInfo () {
return this.$store.state.foo.bar.tar.info
}
}
This is just for a demo purpose, and mine is actually a bit worse, but I ended up doing the same so, I tried minimize the code using a computed prop:
computed: {
info () {
return this.$store.state.foo.bar.tar.info
}
}
Now, I just call info but still, not sure if there is a better way to get values, because sometimes I just need to call info only one in a page, so I have to use the full path or create a computed property for it.
Is there any other way to do this
I always separate vuex into separated modules. For instance if you have store for foo module. I will create file named foo.js which contains
const fooModule = {
state: {
foo: {
bar: {
tar: {
info: 42
}
}
}
},
getters: {
info (state) {
return state.foo.bar.tar.info
}
},
mutations: {
setInfo (state, payload) {
state.foo.bar.tar.info = payload
}
},
actions: {
getInfo ({commit}, payload) {
commit('setInfo', payload)
}
}
}
export default fooModule
Then in your main index vuex, import the module like this way
import Vue from 'vue'
import Vuex from 'vuex'
import fooModule from './foo.js'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
fooModule
}
})
export default store
Then if you wanna get info, you just write your code like this
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters([
'getInfo'
])
}
}
#jefry Dewangga has the the right idea but introducing mapGetters is unnecessary.
VueX by default includes namespacing for modules which allows us to load multiple modules into a store and then reference them with or without namespacing them and it'll figure the rest out.
For Instance if we have the structure of
|-- store
|-- Modules
|-- module1.js
|-- module2.js
|-- module3.js
|-- index.js
We can use index in such a way to bind all of our modules into our Vuex store doing the following:
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules
})
An example of our module1 could be:
const state = {
LoggedIn: true
}
const mutations = {
LOGIN(state) {
state.LoggedIn = true;
},
LOGOFF(state) {
state.LoggedIn = false;
}
}
const actions = {}
export default {
state,
mutations,
actions
}
This in turn gives us the ability to say:
this.$store.commit('LOGIN');
Note that we haven't used any namespacing but as we haven't included any duplicate mutations from within our modules were absolutely fine to implicitly declare this.
Now if we want to use namespacing we can do the following which will explicitly use out module:
this.$store.module1.commit('LOGIN');
MapGetters are useful but they provide a lot of extra overhead when we can neatly digest out modules without having to continuously map everything, unless well we find the mapping useful. A great example of when MapGetters become handy is when we are working many components down in a large project and we want to be able to look at our source without having to necessarily worry about the frontend implementation.