Reputation: 1840
I'm new to Vue, so it's likely I misunderstand something. I want to call a vuex action inside a local function in App.vue
like so:
<template>
<div id="app">
<button @click="runFunction(1)">Test</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default{
data() { return { } },
methods: {
...mapActions(['doAction']),
buttonClicked: (input) => { runFunction(input) }
}
}
function runFunction(input){
doAction({ ID: input });
}
</script>
The action calls a mutation in store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
IDs: []
},
mutations: {
doAction: (state, id) => { state.IDs.push(id) }
},
actions: {
doAction: ({ commit }, id) => { commit('doAction', id) }
}
})
I also have a main.js that sets up the vue:
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
el: '#app',
store,
render: h => h(App)
})
The error I'm getting is:
ReferenceError: doAction is not defined
at runFunction
How can I call the mapped action inside a function? Version is Vue 2.6.10
Upvotes: 1
Views: 3266
Reputation: 29132
There are several problems with defining runFunction
as a 'local function':
function runFunction(input){
doAction({ ID: input });
}
Firstly, this is just a normal JavaScript function and the usual scoping rules apply. doAction
would need to be defined somewhere that this function can see it. There is no magic link between this function and the component defined in App.vue
. The function will be accessible to code in the component, such as in buttonClicked
, but not the other way around.
The next problem is that it won't be available within your template. When you write runTemplate(1)
in your template that's going to be looking for this.runTemplate(1)
, trying to resolve it on the current instance. Your function isn't on the current instance. Given your template includes @click="runFunction(1)"
I'm a little surprised you aren't seeing a console error warning that the click handler is undefined.
mapActions
accesses the store by using the reference held in this.$store
. That reference is created when you add the store
to your new Vue({store})
. The store may appear to be available by magic but it's really just this.$store
, where this
is the current component.
It isn't really clear why you're trying to write this function outside of the component. The simplest solution is to add it to the methods
. It'll then be available to the template and you can access doAction
as this.doAction
.
To keep it as a separate function you'd need to give it some sort of access to the store. Without knowing why you want it to be separate in the first place it's unclear how best to achieve that.
Upvotes: 1
Reputation: 3108
Of course it is not defined outside your instance .... you have to import the exported store
from store.js
on your function component :
<script>
import { mapActions } from 'vuex'
import store from 'store.js'
export default{
data() { return { } },
methods: {
...mapActions(['doAction']),
buttonClicked: (input) => { runFunction(input) }
}
}
function runFunction(input){
store.commit({ ID: input });
}
</script>
Upvotes: 1