Custom vuex store module

Vuex mutations are very similar to events: each mutation has a string type and a handler. The handler function is where we perform actual state modifications, and it will receive the state as the first argument and payload (data) is the second argument. This is how vuex store is operated to modify and update the state.

export default interface IUser {
firstname: string;
lastname: string;
email:string;
};
export {default as IUser} from './i-user'

Note: index.ts file is the file which vue framework will look from for imports.

// our root state is empty because we make use of modules,
// however we do need it for generic arguments and thus we declare it
export default interface IRootState { };
export { default as IRootState } from './i-root-state';
import { StoreOptions } from 'vuex';
import { IRootState } from '../interfaces';
import modules from '../modules';
const config: StoreOptions<IRootState> = {
strict: true,
state() { },
mutations: {},
actions: {},
modules,
};
export default config;
import Vue from 'vue';
import Vuex from 'vuex';
import config from './config';
import { IRootState } from './interfaces';
Vue.use(Vuex);const store = new Vuex.Store<IRootState>(config);export default store;
<template>
<div id="app">
<Home/>
<StoreData/>
</div>
</template>
<script lang="ts">
import Home from './components/Home.vue';
import StoreData from './components/StoreData.vue'
import store from "@/store";
export default {
components: {
Home,
StoreData
},
store
}
</script>
<style>
</style>
export enum GlobalUserActionEnum{
SET_USER = "setUser"
}
export default GlobalUserActionEnum;
import IUser from "@/interfaces/i-user";export enum GlobalUserGetterEnum {
GET_USER = 'getUser'
}
export default GlobalUserGetterEnum;
enum GlobalUserMutationEnum {
Mutate_USER = 'MUTATE_USER',
}
export default GlobalUserMutationEnum;
export const NAMESPACE = 'user';export default NAMESPACE;
import IUser from "@/interfaces/i-user";export type IGlobalUserPayload = Partial<IUser>;

Note: State payload type created as Partial<IUser> so that the state doesn’t force to update all the properties of IUser always instead you can commit partial update of IUser too.

import IUser from "@/interfaces/i-user";export default interface IUserState {
user: IUser;
};
export { default as GlobalUserActionEnum} from './global-user-action-enum';
export { default as GlobalUserMutationEnum } from './global-user-mutation-enum';
export { default as GlobalUserGetterEnum} from './global-user-getters-enum';
export { NAMESPACE } from './global-user-namespace';
export {default as IUSerState } from './i-state-user';
import IUserState from "./static/i-state-user";export const userState: () => IUserState = () => ({
user : {
firstname: '',
lastname: '',
email:''
}
});
import { MutationTree } from 'vuex';
import { GlobalUserMutationEnum } from './static';
import IUserState from "./static/i-state-user";
import { IGlobalUserPayload } from './static/global-user-payload';
export const userMutations: MutationTree<IUserState> = {
[GlobalUserMutationEnum.Mutate_USER](state, payload: IGlobalUserPayload) {
Object.assign(state.user, payload);
},

};
export default userMutations;
import { ActionTree } from 'vuex';
import { GlobalUserActionEnum, GlobalUserMutationEnum } from './static';
import IUserState from './static/i-state-user';
import { IRootState } from '../../interfaces';
import { IGlobalUserPayload } from './static/global-user-payload';
export const userActions: ActionTree<IUserState, IRootState> = {[GlobalUserActionEnum.SET_USER]({ commit }, payload: IGlobalUserPayload) {
commit(GlobalUserMutationEnum.Mutate_USER, payload);
},

};
export default userActions;
import { GetterTree } from 'vuex';
import { IRootState } from '../../interfaces';
import IUser from "@/interfaces/i-user";
import IUserState from './static/i-state-user';
import GlobalUserGetterEnum from './static/global-user-getters-enum';
export const userGetters: GetterTree<IUserState, IRootState> = {[GlobalUserGetterEnum.GET_USER](state): IUser {
return state.user;
},
};
export default userGetters;
import { Module } from 'vuex';
import { IRootState } from '../../interfaces';
import IUserState from "./static/i-state-user";
import { userGetters } from './getters';
import userMutations from './mutations';
import { userActions } from './action';
import { userState } from './state';
const globalUser: Module<IUserState, IRootState> = { namespaced: true,
state: userState,
getters: userGetters,
mutations: userMutations,
actions: userActions,

};
export default globalUser;
import user from './user'export default{
user
};
<template>
<div class="home">
First Name: <input v-model="user.firstname" />
<br />
Last Name: <input v-model="user.lastname" />
<br />
Email: <input v-model="user.email" />
<br />
<button @click="onSave()">Update User in Store</button>
<br />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { IUser } from "@/interfaces";
import { mapActions, mapGetters } from "vuex";
import {
GlobalUserActionEnum,
GlobalUserGetterEnum,
NAMESPACE,
} from "../store/modules/user/static";
export default Vue.component('Home', {

data() {
return {
user : {
firstname: "",
lastname: "",
email: "",
} as IUser,
};
},
methods:{
onSave(){
this.setUser({
firstname: this.$data.user.firstname,
lastname: this.$data.user.lastname,
email: this.$data.user.email,
}
);
alert('User details are saved to store.')
},
...mapActions(NAMESPACE, {
setUser: GlobalUserActionEnum.SET_USER,
}),
},computed:{
...mapGetters(NAMESPACE, {
getUser: GlobalUserGetterEnum.GET_USER,
}),

},
created(){
//Don
this.$data.user.firstname = this.getUser.firstname;
this.$data.user.lastname = this.getUser.lastname;
this.$data.user.email = this.getUser.email;
}
})
</script>
<template>
<div>
<br /><br />
<h1>User Data (update on click) : {{ userData }}</h1>
<h1>User Data (reactive update) : {{ userComputedData }}</h1>
<button
@click="onFetch()">Read User from Store</button>
<br />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import { mapGetters } from "vuex";
import {
GlobalUserGetterEnum,
NAMESPACE,
} from "../store/modules/user/static";
export default Vue.component('StoreData', {

data() {
return {
userData: String,
};
},
methods:{
onFetch(){
this.$data.userData = this.getUser.firstname + ' ' + this.getUser.lastname + ', '+ this.getUser.email;
},

},
computed:{
...mapGetters(NAMESPACE, {
getUser: GlobalUserGetterEnum.GET_USER,
}),
userComputedData(){
return this.getUser.firstname + ' ' + this.getUser.lastname + ', '+ this.getUser.email;
}

},
created(){
this.onFetch();
}
})
</script>

Note: with this approach you will be able to create as many store submodules you want. Simple approach would be to just copy paste the entire user folder and change the name as of your module name.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store