Modules vs Multiple vuex store files - vue.js

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
});
},
}

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

Access app.config.globalProperties in vuex store

I got a vuex store like this:
const state = {
status: '',
};
const getters = {
//...
};
const actions = {
// ...
};
const mutations = {
// ...
};
export default {
namespaced: true,
state,
getters,
actions,
mutations,
}
Now I'd like to access app.config.globalProperties.$notify
In Vue.js2 I was using something like Vue.prototype.$notify, but this is not working anymore.
$notify is also provided like this:
app.use(routes)
.provide('notify', app.config.globalProperties.$notify)
.mount('#app')
Unfortunately I did not find any information about this in the docs yet.
So my question: How can I either inject $notify or access app.config.globalProperties within this store?
From your store and its modules, you could return a store factory -- a function that receives the application instance from createApp and returns a store:
// store/modules/my-module.js
const createStore = app => {
const mutations = {
test (state, { committedItem }) {
app.config.globalProperties.$notify('commited item: ' + committedItem)
}
}
return {
namespaced: true,
//...
mutations,
}
}
export default app => createStore(app)
// store/index.js
import { createStore } from 'vuex'
import myModule from './modules/my-module'
export default app =>
createStore({
modules: {
myModule: myModule(app)
}
})
Then use the store factory like this:
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import createStore from './store'
const app = createApp(App)
app.use(createStore(app)).mount('#app')
demo

How does Vuex 4 createStore() work internally

I am having some difficulty understanding how Veux 4 createStore() works.
In /store/index.js I have (amongst a few other things):
export function createVuexStore(){
return createStore({
modules: {
userStore,
productStore
}
})
}
export function provideStore(store) {
provide('vuex-store', store)
}
In client-entry.js I pass the store to makeApp() like this:
import * as vuexStore from './store/index.js';
import makeApp from './main.js'
const _vuexStore = vuexStore.createVuexStore();
const {app, router} = makeApp({
vuexStore: _vuexStore,
});
And main.js default method does this:
export default function(args) {
const rootComponent = {
render: () => h(App),
components: { App },
setup() {
vuexStore.provideStore(args.vuexStore)
}
}
const app = (isSSR ? createSSRApp : createApp)(rootComponent);
app.use(args.vuexStore);
So, there is no store that is exported from anywhere which means that I cannot import store in another .js file like my vue-router and access the getters or dispatch actions.
import {store} '../store/index.js' // not possible
In order to make this work, I did the following in the vue-router.js file which works but I don't understand why it works:
import * as vuexStore from '../store/index.js'
const $store = vuexStore.createVuexStore();
async function testMe(to, from, next) {
$store.getters('getUser'); // returns info correctly
$store.dispatch('logout'); // this works fine
}
Does Veux's createStore() method create a fresh new store each time or is it a reference to the same store that was created in client-entry.js? It appears it is the latter, so does that mean an application only has one store no matter how many times you run createStore()? Why, then, does running createStore() not overwrite the existing store and initialise it with blank values?
createStore() method can be used on your setup method.
On your main.js, you could do something like this
import { createApp } from 'vue'
import store from './store'
createApp(App).use(store).use(router).mount('#app')
store.js
import { createStore } from 'vuex';
export default createStore({
state: {},
mutations: {},
actions: {},
});
To access your store, you don't need to import store.js anymore, you could just use the new useStore() method to create the object. You can directly access your store using it just as usual.
your-component.js
<script>
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const isAuthenticated = computed(() => store.state.isAuthenticated);
const logout = () => store.dispatch("logout");
return { isAuthenticated, logout };
},
};
</script>
To use your store in the route.js file, you could simply imported the old fashion way.
route.js
import Home from '../views/Home.vue'
import store from '../store/'
const logout = () => {
store.dispatch("auth/logout");
}
export const routes = [
{
path: '/',
name: 'Home',
component: Home
}
]

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.

How to test Vuex module using Mocha and Chai

I'm currently using Nuxt and I would like to do unit testing in my vuex modules.
I'm using vuex modules and here's my index.js
store/index.js
import Vuex from 'vuex';
import * as user from "~/store/modules/users";
const createStore = () => {
return new Vuex.Store({
state: {},
mutations: {},
modules: {
user
}
});
};
export default createStore;
and here's the vuex for users (I made it very simple by mutating the count only but I'm doing api requests here)
store/modules/user.js
export const state = {
count: 0
}
export const mutations = {
INCREMENT(state, user) {
state.count += 1;
}
}
export const actions = {
incrementCount({commit}) {
commit('INCREMENT');
}
}
export const getters = {
count(state) {
return state.count;
}
}
I would like to use Mocha and Chai, for testing state, actions, mutations, and getters for each vuex modules.
Can anyone give a sample for doing a unit test for this?