How to use mapGetters with Vuex Modules - vue.js

i have added modules in store/index.js
import NavMessage from './nav/message/index';
new Vuex.Store({
modules: {
NavMessage,
},
});
my message/index.js
import state from './state';
import getters from './getters';
import mutations from './mutations';
export default {
state,
getters,
mutations,
};
here is getters
const getters = () => ({
getCount: state => {
return state.count;
},
});
export default getters;
i am trying to get data from NavMessage/getCount
...mapGetters({
count: 'NavMessage/getCount',
}),
but i am getting error unknown getter: NavMessage/getCount
help me thank

Below is a working example.
I've made two important changes:
I've added namespaced: true to the module.
I've removed the wrapper function from around the getters.
If you don't want to use namespacing then you'll need to change the mapGetters argument to count: 'getCount' instead. The NavMessage/ prefix is only required with namespacing.
const mapGetters = Vuex.mapGetters
const state = {
count: 6
}
const getters = {
getCount: state => {
return state.count
}
}
const mutations = {}
const NavMessage = {
namespaced: true,
state,
getters,
mutations
}
const store = new Vuex.Store({
modules: {
NavMessage
}
})
const app = new Vue({
store,
computed: {
...mapGetters({
count: 'NavMessage/getCount',
})
}
})
console.log(app.count)
<script src="https://unpkg.com/vue#2.6.10/dist/vue.js"></script>
<script src="https://unpkg.com/vuex#3.1.2/dist/vuex.js"></script>
You've tagged the question with Nuxt. If you are using Nuxt I strongly suggest reading their guide to using the store:
https://nuxtjs.org/guide/vuex-store
Nuxt does things a little differently but as far as I'm aware you still shouldn't have a function wrapper around your getters. The namespaced: true will be added automatically and you shouldn't need to create the new Vuex.Store yourself. Nuxt creates the store itself and adds modules based on the folder structure.

Related

vuex unknown action type: 'auth/Signup'

I was trying to create a signup page using my auth module in vuex. I posted an api for signing up from action in the module. When I tried this code, it said "[vuex] unknown action type: auth/signUp" in the console. Did I do anything wrong? Can anyone solve this?
This is my vuex auth module
// store/auth/index.jx
import auth from '#/API/API_Auth'
const state = () => ({})
const getters=()=>({})
const mutations = () => ({})
const actions = () => ({
signUp({commit},data){
return auth.signUp(data)
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
}
})
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
My vuex store.
// store/index.js
import Vue from "vue";
import Vuex from "vuex"
import auth from './module/auth'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
auth,
},
state:{},
getters:{},
mutations:{},
actions:{},
})
I imported the store and router in main.js
// main.js
import store from "./store"
import router from "./router";
new Vue({
store,
router,
render: (h) => h(App),
}).$mount("#app");
This is my sign up component where I call the action.
// src/component/signup.vue
<script>
export default {
data() {
return {
name: "",
telNumber: "",
};
},
methods: {
handleSubmit() {
let name= this.name
let telNumber= this.telNumber
this.$store.dispatch("auth/signUp", {name,telNumber})
.then(res=>{
this.$router.push({path: 'otp'});
})
.catch(err=>{console.log(err)})
}
}
}
};
</script>
Your Vuex module incorrectly sets actions, mutations, and getters as functions. Only state should be a function, and the rest should be objects:
const state = () => ({}) // ✅ function
const getters = {} // ✅ object
const mutations = {} // ✅ object
const actions = { // ✅ object
signUp({ commit }, data) {}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}

Modules vs Multiple vuex store files

I am working on a project using vue and vuex. And I think most of the people are having the problem, after sometime the store.js (or index.js) is getting too big. So I want to split the store.js file. After some google I found I can use Modules to overcome this problem. BUT I tried also with creating a new Instance of vuex and it works perfectly fine.
Single instance with modules :
---store.js
import Vuex from "vuex";
import thisismodule1 from "./modules/module1";
import thisismodule2 from "./modules/module2";
const createStore = () => {
return new Vuex.Store({
modules: {
module1: thisismodule1,
module2: thisismodule2
}
});
};
export default createStore;
const store = new Vuex.Store({
module
});
Multiple files with multiple instances:
---storeCar.js
---storeHouse.js
---storeTree.js
...
So my question is, is this allowed or do I have to use modules with single instance?
Thank you in advance!
there is a best practice for that:
Create a file. that's name is Shared
Create a Store folder and create a modules folder on it:
you should modules in the modules folder and define your store for a target:
for example:
import * as types from "../types";
const state = {
currentPage: {}
};
const getters = {
[types.avatarManagement.getters.AVATAR_MANAGEMENT_GET]: state => {
return state.currentPage;
}
};
const mutations = {
[types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE]: (
state,
payload
) => {
state.currentPage = payload;
}
};
const actions = {
[types.avatarManagement.actions.AVATAR_MANAGEMENT_ACTION]: (
{ commit },
payload
) => {
commit(types.avatarManagement.mutations.AVATAR_MANAGEMENT_MUTATE, payload);
}
};
export default {
state,
getters,
mutations,
actions
};
Create index.js for define Vuex and import your modules:
index.js file:
import Vue from "vue";
import Vuex from "vuex";
import avatarManagement from "./modules/avatarManagement";
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
avatarManagement
}
});
5) also you can types of your vuex store on Type.js file:
type.js:
export const avatarManagement = {
getters: {
AVATAR_MANAGEMENT_GET: "AVATAR_MANAGEMENT_GET"
},
mutations: {
AVATAR_MANAGEMENT_MUTATE: "AVATAR_MANAGEMENT_MUTATE"
},
actions: {
AVATAR_MANAGEMENT_ACTION: "AVATAR_MANAGEMENT_ACTION"
}
};
***for get data from Store:
computed: {
...mapGetters({
registrationData:types.avatarManagement.AVATAR_MANAGEMENT_GET,
getDataFromStore() {
return this.registrationData;
}
}
***for Change data to Store and mutate that:
methods: {
goToActivity() {
const activity = {
companyList: this.categories
};
this.$store.commit(types.avatarManagement.AVATAR_MANAGEMENT_MUTATE, {
newData
});
},
}

Nuxt acces vuex store inside mixin

I m making small mixin for driving animations based on how user is crawling through page and I need to have access to data stored in Vuex store from that mixin.
Any ides how to pass data from vuex store there, I am getting mad.
pages/index.vue
import Vue from 'vue'
import {ToplevelAnimations} from '~/mixins/toplevel_animations'
export default Vue.extend({
mixins: [
ToplevelAnimations
]
})
mixins/toplevel_animations.js
export const ToplevelAnimations = {
transition(to, from) {
// some logic, here I need to access routes stored in store
return (to_index < from_index ? 'switch-to-left' : 'switch-to-right');
}
}
store/index.js
import {StoreExtensions} from "~/plugins/store_extensions.js";
export const state = () => ({
MAIN_NAV_LINKS: [
{
path: '/',
title: 'Domov',
order: 1
},
// ...etc
],
CURRENT_PAGE_INDEX: 1
})
export const getters = {
getMainNavLinks: (state, getters) => {
return state.MAIN_NAV_LINKS
}
// ..etc
}
export const mutations = {
setCurrentPageIndex(index) {
state.CURRENT_PAGE_INDEX = index
}
// ...etc
}
export const actions = {
nuxtServerInit ({ commit }, req ) {
var page_index = StoreExtensions.calculatePageIndex(req.route.path, state.MAIN_NAV_LINKS)
mutations.setCurrentPageIndex(page_index)
}
}
I never used Vue.extend(), always using .vue files, so it might be different (although it should not). From my experience with mixins in both Vue and Nuxt seems that mixins receive the relevant this context when they are assigned to components. So for me using simple this.$store worked.

Vuex unable to use modules

I am using Vue with Webpacker with Rails. I am having some problem with Vuex, specifially on using modules.
application.js:
import store from '../store/store'
Vue.prototype.$store = store;
document.addEventListener('turbolinks:load', () => {
axios.defaults.headers.common['X-CSRF-Token'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content')
const app = new Vue({
el: '[data-behavior="vue"]',
store
})
})
store.js:
import Vue from 'vue/dist/vue.esm'
import Vuex from 'vuex';
import axios from 'axios';
import itemstore from'./modules/itemstore'
Vue.use(Vuex)
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
const store = new Vuex.Store({
............
modules: {
itemstore
}
})
export default store;
itemstore.js:
import axios from 'axios';
const itemstore = {
state: {
items: [],
},
actions: {
loadItems ({ commit }) {
axios
.get('/items.json')
.then(r => r.data)
.then(items => {
commit('SET_ITEMS', items);
})
}
},
mutations: {
SET_ITEMS (state, items) {
state.items = items
}
},
}
export default itemstore;
In my component:
mounted () {
this.$store.dispatch('loadItems')
},
computed: {
...mapState([
'items'
]),
}
First to get the main store imported I need Vue.prototype.$store = store;
Secondly once i move those states, actions and mutations from store.js to itemstore.js, items gets undefined. What am I doing wrong?
The namespaced setting will cause the actions, mutations and setters of a store to be namespaced based on the module name. The state of a module, however, is always separated off into its own subtree within state, even if namespacing is not being used.
So this won't work:
...mapState([
'items'
]),
This is looking for an items property in the root state.
Instead you can use something like:
...mapState({
items: state => state.itemstore.items
})
You might be tempted to try to write it like this:
...mapState('itemstore', ['items'])
However, passing the module name as the first argument to mapState will only work with namespaced modules.

vuex unknown action type when attempting to dispatch action from vuejs component

I'm using laravel, vue and vuex in another project with almost identical code and it's working great. I'm trying to adapt what I've done there to this project, using that code as boilerplate but I keep getting the error:
[vuex] unknown action type: panels/GET_PANEL
I have an index.js in the store directory which then imports namespaced store modules, to keep things tidy:
import Vue from "vue";
import Vuex from "vuex";
var axios = require("axios");
import users from "./users";
import subscriptions from "./subscriptions";
import blocks from "./blocks";
import panels from "./panels";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
actions: {
},
mutations: {
},
modules: {
users,
subscriptions,
blocks,
panels
}
})
panels.js:
const state = {
panel: []
}
const getters = {
}
const actions = {
GET_PANEL : async ({ state, commit }, panel_id) => {
let { data } = await axios.get('/api/panel/'+panel_id)
commit('SET_PANEL', data)
}
}
const mutations = {
SET_PANEL (state, panel) {
state.panel = panel
}
}
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
Below is the script section from my vue component:
<script>
import { mapState, mapActions } from "vuex";
export default {
data () {
return {
}
},
mounted() {
this.$store.dispatch('panels/GET_PANEL', 6)
},
computed:
mapState({
panel: state => state.panels.panel
}),
methods: {
...mapActions([
"panels/GET_PANEL"
])
}
}
</script>
And here is the relevant code from my app.js:
import Vue from 'vue';
import Vuex from 'vuex'
import store from './store';
Vue.use(Vuex)
const app = new Vue({
store: store,
}).$mount('#bsrwrap')
UPDATE:: I've tried to just log the initial state from vuex and I get: Error in mounted hook: "ReferenceError: panel is not defined. I tried creating another, very basic components using another module store, no luck there either. I checked my vuex version, 3.1.0, the latest. Seems to be something in the app.js or store, since the problem persists across multiple modules.
Once you have namespaced module use the following mapping:
...mapActions("panels", ["GET_PANEL"])
Where first argument is module's namespace and second is array of actions to map.