Let's say i have Vuex store module storeModuleName, and i want to invoke its action from some component.
Component:
export default {
actions: {
close() {
dispatch('storeModuleName/storeModuleAction');
},
}
...
Error:
dispatch is not defined
You need mapActions, mapActions let you connect with actions inside modules
import { mapActions } from "vuex";
export default {
methods: {
...mapActions({
storeModuleActionName: "storeModuleName/storeModuleAction"
})
},
mounted(){
this.storeModuleActionName();
}
}
And then you can use storeModuleActionName as a normal method, Check the link about mapActions
Related
how to use v-model on vuex,
in this case only to show modal box when button is clicked
in this vuex also have separate to module
this is index module
import createPersistedState from 'vuex-persistedstate'
import Vue from 'vue'
import Vuex from 'vuex'
import authentication from './authentication'
import products from './products'
import projects from './projects'
Vue.use(Vuex)
export default new Vuex.Store({
strict: true,
state: {
baseUrl: '/api',
// baseUrl: 'http://localhost:3333/api',
},
mutations: {
},
actions: {
},
modules: {
authentication,
products,
projects,
},
plugins: [
createPersistedState(),
],
})
and this is my module
import HTTP from '../http';
export default {
namespaced: true,
state:{
dialog: false,
},
getters: {
dialog(state){
console.log(state.dialog)
return state.dialog
}
},
mutations: {
closeCard(state){
state.dialog=false;
console.log(state.dialog);
}
}
}
i have try map state and map getter both not function
and this is my vue code
v-model="dialog"
width="500"
i have try use map state or map getter but both not working
import Test from '/components/Test'
export default {
components:{
Test
},
computed: {
dialog:{
get() {
return this.$store.state.dialog.products
},
},
map State('products',[
'dialog'
]),
},
methods:{
map Actions('products',[
'close Card',
])
}
}
and this is my error
Computed property "dialog" was assigned to but it has no setter.
found in
Directly binding a computed property to a v-model is a bad practice as a computed value doesn't have a default setter.
you will need to implement a setter for your computed value. you can read about it here.
you should implement a state action that changes the value of the dialog property and then call it in your setter (and set it to true or false, depending on the case.
Actually there are typo's in your code while called vuex handlers
import {mapState, mapActions } from 'vuex'; // check this line
import Test from '/components/Test'
export default {
components:{
Test
},
computed: {
dialog:{
return this.dialog;
},
...mapState('products',[ // check this line
'dialog'
]),
},
methods:{
...mapActions('products',[ // check this line
'closeCard', // check this line
])
}
}
Also note that you shouldn't directly bind a computed property to a v-model
If I have a store:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
foo: bar
},
mutations: {
updateComponent (state) {
// computation and logic
// update state
this.$refs.myComponent.updateComponent(state.foo)
}
}
}
And I have a component with ref 'myComponent':
<template>
...
</template>
<script>
export default {
...
methods: {
updateComponent(payload) {
// do stuff
}
}
}
</script>
I would like to call the 'updateComponent()' method from the store. I can use this.$refs.myComponent from other views and components, but it doesn't work from the Store. I get error TypeError: Cannot read property 'myComponent' of undefined.
Clearly this is not the correct scope for the this.$refs.myComponent when using from the Store.
Can I call updateComponent() from my store mutation, and how?
You could use vuex's subscribe method. Subscribe your component in it's mounted phase:
mounted() {
this.$store.subscribe((mutation, state) => {
switch(mutation.type) {
case 'updateComponent':
// Update your component with new state data
break;
}
})
}
Reference: https://vuex.vuejs.org/api/#subscribe
When I call a mapped Vuex action in my mounted hook, the action works, but I get "TypeError: xxx is not a function" error in the console.
Here's my whole script section for this component:
<script>
import SideNav from '#/components/SideNav.vue'
import ActionBar from '#/components/ActionBar.vue'
import Summaries from '#/components/Summaries.vue'
import { mapState, mapActions } from 'vuex'
export default {
components: { SideNav, ActionBar, Summaries },
computed: {
...mapState(['dataLoading']),
...mapActions(['init'])
},
mounted() {
this.init();
}
}
</script>
You should map Actions as methods instead of computed, see dispatch actions in components:
computed: {
...mapState(['dataLoading'])
},
methods: {
...mapActions(['init'])
},
mounted() {
this.init();
}
I'm new with vue.js and vuex and I've an issue with the mapstate object, first I've only one module in my store:
-Store
-index.js
-mutations.js
-actions.js
-state.js
state.js :
export default {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
So when I try to access the userInfo object everything works correctly:
computed: {
...mapState(["userInfo"]),
}
Then I decided to create modules:
-Store
-modules
-ldap.js
-commons.js
-index.js
So the userInfo is in the commons.js file and now when I try to get the object I always get undefined:
commons.js
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
actions,
mutations,
state
}
Component.vue
computed: {
...mapState(["userInfo"]), // <---- undefined
}
main.js :
import Vue from 'vue'
import Vuex from 'vuex'
import commons from './commons'
import ldap from './modules/ldap'
Vue.use(Vuex)
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Can you tell me how to access the userInfo object?
Thanks.
Considering:
Your commons.js is as follows:
// state
const state = {
userInfo: {
messages: [{ 1: 'test', 2: 'test' }],
notifications: [],
tasks: []
}
}
export default {
namespaced: true, // <== make sure this is defined
actions,
mutations,
state
}
And main.js imports it like:
import commons from './commons'
// ..
export default new Vuex.Store({
modules : {
commons,
ldap
}
})
Then update on Component.vue:
import { mapState } from 'vuex'
// ...
computed: {
...mapState('commons', ["userInfo"]), // <== add module name here
}
Or
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('commons')
// ... notice module name above ^^^^^^^^^
computed: {
...mapState(["userInfo"]),
}
"[vuex] unknown mutation type: "
Since you are now namespacing your commons module, that modules' mutations now must be prefixed.
So, say you had a mutation like:
const mutations = {
changeName(state, data) {
state.name = data;
}
}
export default {
namespaced: true,
actions,
mutations,
state
}
And you used it like:
this.$store.commit('changeName', "New Name");
Now use it like:
this.$store.commit('commons/changeName', "New Name");
I guess you have namspaced your modules by adding namespaced: true in your module.
So you should pass the module name as the first argument to the mapState helpers so that all bindings are done using that module as the context. See Binding Helpers with Namespace
computed: {
...mapState('commons' , ["userInfo"])
}
You have to define each module as a individual store, here some pseudo example.
// authStore.js
import mutations from './authMutations'
import actions from './authActions'
import getters from './authGetters'
const initialState = {
...
}
export default {
state: initialState,
mutations,
actions,
getters
}
Then, register the modules
import authStore from './authStore'
const store = new Vuex.Store({
modules: {
{...authStore, namespaced: true},
{...postStore, namespaced: true} // some other module defined like auth
}
})
new Vue({
....
store: store
})
And then, on the component use it:
import { createNamespacedHelpers } from 'vuex'
// map state and actions of the module
const { mapState, mapActions } = createNamespacedHelpers('auth')
export default {
computed: {
...mapState({
prop1: 'prop1'
})
}
}
Vuex modules docs
It is really unclear in the documentation but namespaced: true is required to use the map functions.
At least as of the last comment in this discussion
https://github.com/vuejs/vuex/issues/855
Without the need to namespace your modules you can use the callback variant of mapstate:
computed: {
...mapState({
userInfo: state => state.commons.userInfo,
}),
},
I'm using the following code to increment a counter in store.js using Vuex. Don't know why, when I click the increment button, it says:
[vuex] unknown action type: INCREMENT
store.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
var store = new Vuex.Store({
state: {
counter: 0
},
mutations: {
INCREMENT (state) {
state.counter++;
}
}
})
export default store
IcrementButton.vue
<template>
<button #click.prevent="activate">+1</button>
</template>
<script>
import store from '../store'
export default {
methods: {
activate () {
store.dispatch('INCREMENT');
}
}
}
</script>
<style>
</style>
You have to use commit in the methods as you are triggering a mutation, not an action:
export default {
methods: {
activate () {
store.commit('INCREMENT');
}
}
}
Actions are similar to mutations, the difference being that:
Instead of mutating the state, actions commit mutations.
Actions can
contain arbitrary asynchronous operations.