I'm testing Vuejs 2.0 & Vuex with modules design but components can't access to action methods.
my component :
import {mapGetters, mapActions} from 'vuex'
export default {
computed: mapGetters({
clients: 'clients',
fields: 'fields'
}),
methods: mapActions({
init: 'init'
}),
created: () => {
console.log(this.init)
}
}
my module :
const state = {
'fields': [
{
'field': 'name',
'label': 'Nom'
},
{
'field': 'adresse',
'label': 'Adresse'
},
{
'field': 'amount',
'label': 'Amount'
},
{
'field': 'contact',
'label': 'Contact'
}
],
items : []
}
export const SET_CLIENTS = 'SET_CLIENTS'
const mutations = {
[SET_CLIENTS] (state, clients) {
state.items = clients;
}
}
const actions = {
init: ({ commit }, payload) => {
let clients = []
for(let i = 0; i < 100; i++){
clients.push({
'name': 'Client '+i,
'adresse': '14000 Caen',
'amount': '1000',
'contact': 'contact#client'+i+'.com'
})
}
commit(SET_CLIENTS, { clients })
}
}
const getters = {
clients (state) {
return state.items;
},
fields (state) {
return state.fields;
}
}
export default {
state,
mutations,
getters,
actions
}
the store creation :
import Vuex from 'vuex'
import clients from './modules/clients'
import filters from './modules/filters'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
clients,
filters
}
})
All the project code is available here :https://github.com/robynico/vuejs-2.0-modules
If you test it, you will see that init method is undefined at component creation.
Thanks in advance!
I think you are exporting your store modules wrong. Try this:
Inside your module.js:
export default {
state: {}, // define your state here
getter: {}, // define your getters here
actions: {}, // define your actions here
mutations: {} // define your mutations here
}
Then inside your store:
import Vue from 'vue'
import Vuex from 'vuex'
import module from './modules/module.js'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
module // your moudle
}
})
export default store
Related
I wrote the following code but it shows an error. What is the reason for this?
Error
[vuex] unknown action type: showRegisterLogin/show
HomePage.vue // component
When using the sh method This error is caused
import { mapState, mapActions } from "vuex";
export default {
name: "HomePage",
components: {
RegisterLogin
},
data() {
return {}
},
computed: {
...mapState({
showRegisterLogin: state => state.showRegisterLogin.show
}),
},
methods: {
sh() {
this.$store.dispatch('showRegisterLogin/show');
}
}
}
/ store / modules / showRegisterLogin.js
// States
const state = {
show: false,
};
// Getters
const getter = {
show (state) {
return state.show;
}
};
// Mutations
const mutation = {
showPage (state) {
return state.show = true;
},
hidePage (state) {
return state.show = false;
}
};
// Actions
const action = {
show({ commit }) {
commit('showPage');
},
hide({ commit }) {
commit('hidePage');
}
};
export default {
namespaced: true,
state,
getter,
mutation,
action
}
/ store / store.js
'use strict';
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import showRegisterLogin from "./modules/showRegisterLogin";
export default new Vuex.Store({
modules: {
showRegisterLogin,
}
});
I also imported the store.js file into app.js and registered it in new vue
The structure of the store, module, and component are fine, except for the name of the store objects in your module:
getter should be getters
mutation should be mutations
action should be actions
Probably just typos. Those can't be arbitrarily named since Vuex looks specifically for those keys.
I would like to test if my getter is called in my component or view, but I don't understand how can it.
My method in the component :
computed: {
...mapGetters({ item: 'moduleA/getData' }),
},
And this is my unit test declaration :
beforeEach(() => {
store = new Vuex.Store({
modules: {
moduleA: {
state: {},
getters: {
getData() {
return { item: { name: 'test' } };
},
},
},
},
});
wrapper = shallowMount(MyComponent, {
store,
});
});
And I try to test if the data is loaded in my template:
it('should check if name is thruthy', () => {
expect(wrapper.find('.classA').text()).toEqual('test');
});
my component :
<template>
<v-content>
<ComponentA v-if="item.name"
key="keyA" ></ComponentA>
<ComponentB v-else key="keyA"></ComponentB>
</v-content>
</template>
<script>
import { mapGetters } from 'vuex';
import ComponentA from '#/components/ComponentA.vue';
import ComponentB from '#/components/ComponentB.vue';
export default {
/**
* Component's name :
*/
name: 'ViewA',
/**
* Component's used :
*/
components: {
ComponentA,
ComponentB,
},
/**
* computed's used :
*/
computed: {
...mapGetters({ item: 'moduleA/getData' }),
},
};
</script>
and my getter in the moduleA :
const getters = {
getData: state => state.data,
};
But I have this message:
TypeError: Cannot read property 'name' of undefined
Why? Thank you for your help.
As shown in docs, shallowMount's options has field named localVue. To solve your problem you should create a localVue, using createLocalVue and pass it to shallowMount.
createLocalVue returns a Vue class for you to add components, mixins
and install plugins without polluting the global Vue class.
import Vuex from 'vuex'
import { createLocalVue, shallowMount } from '#vue/test-utils'
beforeEach(() => {
const localVue = createLocalVue()
localVue.use(Vuex)
store = new Vuex.Store({
modules: {
moduleA: {
state: {},
getters: {
getData() {
return { item: { name: 'test' } }
},
},
},
},
})
wrapper = shallowMount(MyComponent, {
localVue,
store,
})
})
I'm trying to split up my Nuxt Vuex store files into separate files. And NOT have all Vuex getters, mutations and actions into one huge file. This demo project is on Github by the way.
I'v read this official Nuxt Vuex Store documentation; but can't seem to get it working. It's a bit vague on where to put stuff.
I have the following in these files:
Below is my: store/index.js
import Vue from "vue";
import Vuex from "vuex";
import Auth from "./modules/auth";
Vue.use(Vuex);
export const store = () => {
return new Vuex.Store({
state: {
},
modules: {
Auth
}
})
}
This is in my: store/auth.js
const state = () => {
username: null
};
const getters = {
username: state => {
return state.username;
},
isAuthenticated: state => {
return state.username != null;
}
};
const mutations = {
login: (vuexContext, username) => {
vuexContext.username = username;
this.$router.push("/dashboard");
},
logout: vuexContext => {
vuexContext.username = null;
this.$router.push("/");
}
};
const actions = {
};
export default {
state,
getters,
mutations,
actions,
};
And finally in my: pages/index.vue
This is where I'm calling that login mutation:
<script>
export default {
layout: "non-logged-in",
data() {
return {
username: null
}
},
methods: {
onSubmit() {
this.$store.commit("login", this.username);
}
}
}
</script>
The error I'm getting:
[vuex] unknown mutation type: login
What am I doing wrong here? I thought i'm importing all the stuff correctly in the store/index.js
You have to export your store constant like this inside your store/index.js file:
export default store
Put this code line at the end of your file.
So as #jeremy.raza described this is what I changed in order to get it working:
store/index.js
import Vue from "vue";
import Vuex from "vuex";
import Auth from "./modules/auth";
Vue.use(Vuex)
const store = () => {
return new Vuex.Store({
state: {
},
modules: {
Auth
}
})
}
export default store;
Changes in the store/auth.js
Note the changes in how I wrote the state, getters and mutations method notation.
const state = () => ({
username: null
});
const getters = {
username(state) {
return state.username;
},
isAuthenticated(state) {
return state.username != null;
}
};
const mutations = {
login(vuexContext, username) {
vuexContext.username = username;
this.$router.push("/dashboard");
},
logout(vuexContext) {
vuexContext.username = null;
this.$router.push("/");
}
};
const actions = {
};
export default {
state,
getters,
mutations,
actions,
};
In my /src/store/ folder I have actions.js, index.js, mutations.js and state.js which contain the following info
actions.js
export default {}
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state,
actions,
mutations
})
mutations.js
export default {
TOGGLE_LOADING (state) {
state.callingAPI = !state.callingAPI
},
TOGGLE_SEARCHING (state) {
state.searching = (state.searching === '') ? 'loading' : ''
},
SET_USER (state, user) {
state.user = user
},
SET_TOKEN (state, token) {
state.token = token
}
}
and state.js
export default {
callingAPI: false,
searching: '',
serverURI: 'http://10.110.1.136:8080',
user: null,
token: null,
userInfo: {
messages: [{1: 'test', 2: 'test'}],
notifications: [],
tasks: []
}
}
Now, when a user logs in, I keep the state in as
this.$store.commit('SET_USER', response.data)
Now, when a user logs out, I run my components/logout.vue file in which it has the following code:
export default {
data() {},
created() {
localStorage.setItem('vuex', null);
this.$store.commit('SET_USER', null);
window.localStorage.clear();
window.sessionStorage.clear();
}
}
But for some reason, the data is somehow persisted.
have you tried to import your store into the logout.vue component?
const store = require('path/to/index.js');
then in your created method, try
store.default.commit('SET_USER', null);
i just wanna create dynamic registered module in vuex, but it seems doesnt work.
this is my store file
import Vuex from 'vuex'
import descriptionModule from './module/descriptionModule';
const {state: stateModule, getters, mutations} = descriptionModule;
const createStore = () => {
return new Vuex.Store({
state: {
descriptions: [],
},
mutations: {
addDescriptions(state, payload){
state.descriptions.push(state.descriptions.length + 1);
createStore().registerModule(`descriptionModule${payload}`, {
state: stateModule,
getters,
mutations,
namespaced: true // making our module reusable
});
}
}
})
};
export default createStore
and this is my custom module that i will registered
const state = () => {
return {description: ''}
};
const getters = {
description: (state) => state.description
};
const mutations = {
updateDescription(state, payloads){
state.description = payloads;
}
};
export default {
state,getters,mutations
}
and then this is my custom methods that will call addDescriptions mutation and commit updateDescription from registeredModule
beforeMount(){
console.log("hahahaha");
this.$store.commit('addDescriptions', this.id);
},
... more code ....
methods: {
onType(editor, content){
console.log(this.$store.state.a);
console.log(this.$store.state);
console.log(this.$store);
this.$store.commit(`descriptionModule${this.id}/updateDescription`, content, {root: true})
}
}
every onType called, i get an error unknown mutation type: descriptionModuleeditor1/updateDescription in browser.
currently iam following this solution link , but it doesnt work for me :(
can anyone solve this,,, sorry for bad english
invoke $store.registerModule() via component/pages on beforeMount():
beforeMount(){
this.$store.registerModule(`descriptionModule${this.id}`, {
state: stateModule,
getters,
mutations,
namespaced: true // making our module reusable
});
},