I define a store with two modules, and I'm trying to access one module action, I tried to do
this.$store.dispatch('load');
But I get:
[vuex] unknown action type: load
I tried another options, thing that I found in google , but nothing worked, what is the right way to access module actions?
This is my code:
Vuex definition:
let session = require('./store/session.js');
let options = require('./store/options.js');
const store = new Vuex.Store({
modules: {
session: session,
options: options,
},
});
options.js
export default {
state: {
data: null,
},
mutations: {
setOptions (state, payload) {
console.log(payload);
}
},
actions: {
load( { commit }) {
$.getJSON('options')
.then(function (data) {
commit('setOptions', data);
});
}
},
getters: {
}
}
and my app component:
export default {
beforeCreate() {
this.$store.dispatch('load');
}
}
my vue build:
new Vue({
el: "#app",
router,
store,
render: h => h(App)
});
I would consider using the mapActions helper from vuex. Documentation for this can be found at https://vuex.vuejs.org/guide/actions.html#dispatching-actions-in-components .
example from this page is as follows:
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // map `this.increment()` to `this.$store.dispatch('increment')`
// `mapActions` also supports payloads:
'incrementBy' // map `this.incrementBy(amount)` to `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // map `this.add()` to `this.$store.dispatch('increment')`
})
}
}
I solver the problem
Instead of doing
let options = require('./store/options.js');
I did:
import options from './store/options.js'
Now it works
Related
I try to implement vuex modules and understand usage. While trying to import modules in my home.vue, I have found this solution:
import { FETCH_INDEX_ARTICLES } from "#/store/types/actions.type.js";
// imports this => export const FETCH_INDEX_ARTICLES = "fetchIndexArticles"
import { mapGetters, mapActions} from 'vuex'
export default {
name: "Home",
data() {
return {}
},
computed: {
...mapGetters(['articles']),
},
methods: {
...mapActions([FETCH_INDEX_ARTICLES])
}
created() {
this.$store.dispatch(FETCH_INDEX_ARTICLES);
}
};
but instead I get
vuex.esm.js?2f62:438 [vuex] unknown action type: fetchIndexArticles
vuex.esm.js?2f62:950 [vuex] unknown getter: articles
store/index.js
export default new Vuex.Store({
modules: {
articles,
}
});
store/modules/articles.js
const state = {
articles: [],
};
const getters = {
articles(state) {
return state.articles;
},
};
const mutations = {
[SET_ARTICLES] (state, pArticles) {
state.article = pArticles
state.errors = {}
}
}
const actions = {
[FETCH_INDEX_ARTICLES] (context) {
context.commit(FETCH_START)
return ApiService
.get('/articlelist/index/')
.then((data) => {
context.commit(SET_ARTICLES, data.articles);
context.commit(FETCH_END)
})
.catch((response) => {
context.commit(SET_ERROR, response.data.errors);
})
}
};
export default {
namespaced: true,
state,
getters,
actions,
mutations
}
How can I correctly import vuex module?
Thanks
You must specify your modules,
Your way is valid when you import your modules directly into your component
...mapGetters('articles', {
article: 'articles',
})
this.article(2)
https://vuex.vuejs.org/guide/modules.html#binding-helpers-with-namespace
To facilitate the use I use the method dispatch for actions
this.$store.dispatch('articles/FETCH_INDEX_ARTICLES', {anydata})
First of all, good day everyone on this beautiful day. I created a simple jsfiddle that I'll use as an example to describe my problem.
https://jsfiddle.net/Mertakus/cokedgm2/13/
The problem I experience is that although this jsfiddle works to mutate the state of the message, in the Vue app im working on, I divided my store into modules, cuz my store gets bloated otherwise.
So I got a basic.js file where I'm doing the EXACT same thing as in the jsfille, and in my store.js file imported the file and registered the file. E.G:
export default {
strict: true,
state: {
fields: mainFields.basic,
message: 'Hello Vuex'
},
getters: {
getBasic: state => state
},
mutations: {
updateMessage (state, message) {
state.message = message
}
}
}
My main store.js file:
import Vue from "vue"
import Vuex from "vuex"
import basic from "./modules/basic"
Vue.use(Vuex)
export default new Vuex.Store ({
// strict: true,
modules: {
basic
},
// If I uncomment this, it'll work
// state: {
// message: 'Hello Vuex'
// },
// mutations: {
// updateMessage (state, message) {
// state.message = message
// }
// }
})
For some reason, this doesn't work. With the Vue devtool I figured out that the updateMessage mutations does get fired, and the payload is updated, however it isn't displayed on the screen. When I copy -> paste the above logic in the main store.js file, it does render on the screen.
Since it's vuex module, you need to use this.$store.state.basic.message instead.
const basic = {
strict: true,
state: {
message: 'Hello Vuex'
},
getters: {
getBasic: state => state
},
mutations: {
updateMessage (state, message) {
state.message = message
}
}
}
const store = new Vuex.Store({
modules: {
basic
},
})
new Vue({
store,
el: '#app',
computed: {
message: {
get () {
console.log(this.$store.state)
return this.$store.state.basic.message
},
set (value) {
this.$store.commit('updateMessage', value)
}
}
},
methods: {
updateMessage (e) {
this.$store.commit('updateMessage', e.target.value)
}
}
})
Demo here https://jsfiddle.net/ittus/0n183xty/1/
So, in my project (Vue-cli + TypeScript) I need to store user data to locaStorage. For this purpose I decide to use vuex-persist (npm plugin) alongside with vuex. But in DevTool, in localStorage doesn't appear anything. What is wrong in my code. Thank you in advance.
In precedent project I already used this combination of tools, and they work fine. In this project I use the same configuration, and it doesn't work . And this is the most strange thing.
This is StructureModule.ts
import { ActionTree, MutationTree, GetterTree, Module } from "vuex";
const namespaced: boolean = true;
interface IDataStructure {
name: string;
type: string;
description: string;
}
interface IStructureState {
name: string;
description: string;
props: IDataStructure[];
}
export interface IState {
structures: IStructureState[];
}
export const state: IState = {
structures: [
{
name: "",
description: "",
props: [
{
name: "",
type: "",
description: "",
},
],
},
],
};
export const actions: ActionTree<IState, any> = {
addNewDataStructure({ commit }, payload: IStructureState): void {
commit("ADD_DATA_STRUCTURE", payload);
},
updateDataStructure({ commit }, payload: IStructureState): void {
commit("UPDATE_EXISTING_DATA_STRUCTURE", payload);
},
clearDataStructure({ commit }, { name }: IStructureState): void {
commit(" CLEAR_DATA_STRUCTURE", name);
},
};
export const mutations: MutationTree<IState> = {
ADD_DATA_STRUCTURE(state: IState, payload: IStructureState) {
if (state.structures[0].name === "") {
state.structures.splice(0, 1);
}
state.structures.push(payload);
},
CLEAR_DATA_STRUCTURE(state: IState, name: string) {
state.structures.filter((structure: IStructureState) => {
if (structure.name === name) {
state.structures.splice( state.structures.indexOf(structure), 1);
}
});
},
UPDATE_EXISTING_DATA_STRUCTURE(state: IState, payload: IStructureState) {
state.structures.map((structure: IStructureState) => {
if (structure.name === payload.name) {
state.structures[state.structures.indexOf(structure)] = payload;
}
});
},
};
export const getters: GetterTree<IState, any> = {
dataStructureByName(state: IState, structName: string): IStructureState[] {
const structure: IStructureState[] = state.structures.filter((struct: IStructureState) => {
if (struct.name === structName) {
return struct;
}
});
return structure;
},
dataStructures(): IStructureState[] {
return state.structures;
},
};
export const StructureModule: Module<IState, any> = {
namespaced,
state,
mutations,
actions,
getters,
};
This is index.ts
import Vue from "vue";
import Vuex, { ModuleTree } from "vuex";
import VuexPersistence from "vuex-persist";
import { StructureModule , IState} from "./modules/StructureModule";
Vue.use(Vuex);
const storeModules: ModuleTree<IState> = {
StructureModule,
};
const vuexPersistentSessionStorage = new VuexPersistence({
key: "test",
modules: ["StructureModule"],
});
export default new Vuex.Store<any>({
modules: storeModules,
plugins: [vuexPersistentSessionStorage.plugin],
});
This is main.ts
import store from "#/store/index.ts";
import * as $ from "jquery";
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
global.EventBus = new Vue();
(global as any).$ = $;
Vue.config.productionTip = false;
console.log(store);
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
This is vue.config.js
module.exports = {
transpileDependencies: ["vuex-persist"],
};
This is store in vue-devtool
And this is dev-tool localStorage
I expect that in localstorage to appear an storage with key "test" with predefined values, but instead of this localStorage is empty.
As said in the guide
The only way to actually change state in a Vuex store is by committing
a mutation
https://vuex.vuejs.org/guide/mutations.html
I don't see any mutation in your code.
Otherwise, you should take a look at https://github.com/robinvdvleuten/vuex-persistedstate, it seems to be more popular, and I've been using it without any problem.
Usage is very simple : you just need to declare a plugin inside your store:
import createPersistedState from 'vuex-persistedstate'
const store = new Vuex.Store({
// ...
plugins: [createPersistedState()],
})
I found solution for this problem.
In my case i just remove namespaced from
export const StructureModule: Module<IState, any> = {
namespaced, <----- This
state,
mutations,
actions,
getters,
};
It seems namespaced should be used only if you have more than one module.
I have a Vue component that uses Vuex with namespaced modules.
// Main Component
import store from './store';
import {mapState, mapGetters, mapActions} from 'vuex';
new Vue({
store,
computed: {
...mapState({
showModal: state => state.showModal,
}),
computed: {
...mapState('ModuleA', {
a: state => state.a,
}),
...mapState('ModuleB', {
b: state => state.b,
}),
...mapGetters('ModuleA', { getA: 'getA' } ),
...mapGetters('ModuleB', { getB: 'getB' } ),
},
methods: {
...mapActions('ModuleA', [ 'doSomeA']),
...mapActions('ModuleB', [ 'doSomeB']),
},
mounted() {
let payLoad = { ... },
this.doSomeA(payload); // I never see this getting dispatched
}
// Store
export default new Vuex.Store({
modules: { ModuleA, ModuleB }
...
}
// Module A
export default {
namespaced: true,
actions: {
doSomeA: ({dispatch, commit, getters, rootGetters}) => payload => { // do something with payload }
...
}
Since I have mapped the action from my namespaced module I am simply calling the action like normal method in my component. But somehow its not dispatching the action. Any idea what is going wrong here?
I'm new to Vue.js and looking for the equivalent of a service in AngularJS, specifically for storing data once and getting it throughout the app.
I'll be mainly storing the results of network requests and other promised data so I don't need to fetch again on very state.
I'm using Vue.JS 2.0 with Webpack.
Thanks!
I think what u are seeking for is vuex, which can share data from each component.
Here is a basic demo which from my code.
store/lottery.module.js
import lotteryType from './lottery.type'
const lotteryModule = {
state: {participantList: []},
getters: {},
mutations: {
[lotteryType.PARTICIPANT_CREATE] (state, payload) {
state.participantList = payload;
}
},
actions: {
[lotteryType.PARTICIPANT_CREATE] ({commit}, payload) {
commit(lotteryType.PARTICIPANT_CREATE, payload);
}
}
};
export default lotteryModule;
store/lottery.type.js
const PARTICIPANT_CREATE = 'PARTICIPANT_CREATE';
export default {PARTICIPANT_CREATE};
store/index.js
Vue.use(Vuex);
const store = new Vuex.Store();
store.registerModule('lottery', lotteryModule);
export default store;
component/lottery.vue
<template>
<div id="preparation-container">
Total Participants: {{participantList.length}}
</div>
</template>
<script>
import router from '../router';
import lotteryType from '../store/lottery.type';
export default {
data () {
return {
}
},
methods: {
},
computed: {
participantList() {
return this.$store.state.lottery.participantList;
}
},
created() {
this.$store.dispatch(lotteryType.PARTICIPANT_CREATE, [{name:'Jack'}, {name:'Hugh'}]);
},
mounted() {
},
destroyed() {
}
}
</script>
You don't need Vue-specific services in Vue2 as it is based on a modern version of JavaScript that uses Modules instead.
So if you want to reuse some services in different locations in your code, you could define and export it as follows:
export default {
someFunction() {
// ...
},
someOtherFunction() {
// ...
}
};
And then import from your Vue code:
import service from 'filenameofyourresources';
export default {
name: 'something',
component: [],
data: () => ({}),
created() {
service.someFunction();
},
};
Note that this is ES6 code that needs to be transpiled to ES5 before you can actually use it todays browsers.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export