80

I'm trying to switch to using Vuex instead of my homegrown store object, and I must say I'm not finding the docs as clear as elsewhere in the Vue.js world. Let's say I have a Vuex module called 'products', with its own state, mutations, getters, etc. How do I reference an action in that module called, say, 'clearWorking Data'? The docs give this example of accessing a module's state:

store.state.a // -> moduleA's state

But nothing I can see about getters, mutations, actions, etc.

Soviut
  • 88,194
  • 49
  • 192
  • 260
John Moore
  • 6,739
  • 14
  • 51
  • 67
  • 9
    Agree: the docs for vuex are abysmal. Really not helpful. – geoidesic Apr 29 '18 at 23:33
  • 2
    @geoidesic i've definitely noticed areas that could be better. Have you considered raising an issue on GitHub with suggested improvements? – bigsee Apr 09 '19 at 11:31

9 Answers9

189

In Addition to the accepted answer I wanna provide you with a workarround for the getter which is missing in the answer.

Debug the Store
In any case you can call console.log(this.$store) to debug the Store.
If you do so you will see the getters are prefixed with the namespace in their name. enter image description here

Access namespaced getter

this.$store.getters['yourModuleName/someGetterMethod']

Dispatch namespaced

this.$store.dispatch('yourModuleName/doSomething')

Dispatch namespaced with params

this.$store.getters['yourModuleName/someGetterMethod'](myParam)

Conclusion
The key is to handle the namespace like a file System like Justin explained.

Edit: found a nice library for handling vuex Store
In addition to the basic knowledge I'd like to add this vuex library as a nice addition for working effectivly and fast with the vuex store. https://github.com/davestewart/vuex-pathify .
It looks pretty interesting and cares much of the configuration for you and also allows you to handle 2waybinding directly with vuex.

** Edit: Thanks to the other Answers. Added Dispatching method with params for wholeness.

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Gkiokan
  • 3,492
  • 2
  • 22
  • 24
  • 15
    So where I was using `return store.getters.individuals` before adding namespaced=true, I now have to use `return store.getters['individual/individuals']` Thank you for this additional answer. Spent half an hour on this and found zero examples of accessing the namespaced getter until your answer here. – shanemgrey Aug 13 '17 at 15:41
  • The reason for the change should have been obvious to me. You can't use dot notation for a property with a name that includes special characters like '/', so you have to use bracket notation. could use bracket notation in all cases, it's just not as elegant. So dot notation is often used unless it can't be like in this example. – shanemgrey Aug 13 '17 at 15:46
  • Don't forget to set [`namespaced: true`](https://vuex.vuejs.org/en/modules.html#namespacing) in each of your module, to be able to use getters like that. – Scofield Oct 11 '17 at 12:01
  • 1
    Thank you for complementing the getters part that was not exposed in the accepted answer...you made my day – Pavarine May 30 '18 at 22:40
  • 3
    Access namespaced getter! YES! Thank you! Why?.. Why they didn't include this in documentation? ‍♂️ – Pavel Kovalev Oct 26 '18 at 05:28
  • how can pass payload in namespaced dispatch? – Oussama He Jul 31 '19 at 12:27
  • See updated Post or next Answer below. ```this.$store.getters['yourModuleName/someGetterMethod'](myParam)``` – Gkiokan Aug 08 '19 at 19:21
  • Very helpful answer indeed. Thanks a million – Hussain Rahimi Apr 21 '20 at 14:41
  • @shanemgrey the obvious answer is the one that i'm sure we all tried first and didn't work getters.namespace,function, so then you look at the manual and see "Getters are also registered in the global namespace by default. However, this currently has no functional purpose" so there must be the approved way of accessing but seems to be completely absent from the manual, though im guessing the approved method is `$store.modules.name.getters` – MikeT Aug 26 '21 at 15:50
42

In your example it would be store.dispatch('products/clearWorkingData') you can think of actions/mutations as a file system in a way. The deeper the modules are nested the deeper in the tree they are.

so you could go store.commit('first/second/third/method') if you had a tree that was three levels deep.

Justin MacArthur
  • 4,022
  • 22
  • 27
  • 3
    Ah, OK! Is this dependent on setting `namespaced: true`? – John Moore Jan 24 '17 at 18:42
  • 1
    @JohnMoore Yes sorry for not mentioning it, any module you want to have separated needs to have `namespaced: true,` set. if not then it'll inherit the namespace of the parent module. – Justin MacArthur Jan 24 '17 at 19:02
  • @JustinMacArthur does this method of accessing data from a module within a vuex store also work if you are trying to access it from within the composition api setup() method? – CodeConnoisseur Aug 25 '21 at 13:48
  • 1
    @PA-GW This was written for V2.x and the appropriate Vuex. I'm not sure if it would work with the composition api. I don't see why not depending on execution time. – Justin MacArthur Aug 26 '21 at 15:06
30

As another addition to the accepted answer, if you need to pass parameter(s) to the getter (for instance to fetch a specific item from the store collection), you need to pass it as follows:

this.$store.getters['yourModuleName/someGetterMethod'](myParam)

I don't think I like this notation very much, but it is what it is - at least for the moment.

Peter Kassenaar
  • 301
  • 3
  • 4
  • Using Vuex4, in setup of composition api, I added the following. setup(props) { const store = useStore() const randomNumber = computed(() => store.getters['item/getRandomNumber']) return { randomNumber }; }, But getting lint error: @typescript-eslint/no-unsafe-member-access: Unsafe member access ['item/getRandomNumber'] on an any value. – Ammamon Apr 02 '21 at 05:42
22

Try this approach!

getCounter(){
  return this.$store.getters['auth/getToken'];     
}

auth is my module name and getToken is my getter.

kissu
  • 40,416
  • 14
  • 65
  • 133
Hardik Raval
  • 3,406
  • 1
  • 26
  • 28
15

Using Vuex mapGetters and mapActions you can now do this pretty easily. But I agree, it still isn't very obvious in the documentation.

Assuming your store module 'products' has a getter called 'mostPopular' and an action called 'clearWorkingData':

<template>
 <div>
  <p>{{mostPopularProduct}}<p>
  <p><button @click="clearProductData">Clear data</button></p>
 </div>
</template>
<script>
import { mapGetters, mapActions } from "vuex";

export default {
 computed: mapGetters({
  mostPopularProduct: "products/mostPopular"
 }),
 methods: mapActions({
  clearProductData: "products/clearWorkingData"
 })
}
</script>
Ben Hoffmann
  • 309
  • 2
  • 5
1

The mapGetters helper simply maps store getters to local computed properties:

    import { mapGetters } from 'vuex'

    export default {
  // ...
  computed: {
    // mix the getters into computed with object spread operator
    ...mapGetters([
      'doneTodosCount',
      'anotherGetter',
      // ...
    ])
  }
}
If you want to map a getter to a different name, use an object:

    ...mapGetters({
  // map `this.doneCount` to `this.$store.getters.doneTodosCount`
  doneCount: 'doneTodosCount'
})
Bhushan Patil
  • 105
  • 2
  • 8
  • This doesn't account for the core of the question: how to access a specific vuex _module's_ getter – mix3d Sep 25 '19 at 16:59
1

You have to be aware of using namespaced: true when configuring particular store object

Can PERK
  • 590
  • 8
  • 24
0

In Addition to the accepted answer, I feel it's not a good idea to mutate the state and commit the mutation directly in component. Thumb rule I follow is, Always use an action to commit the mutation and state only mutate inside mutations. Use getters to get a transformed state.

Getters can be mapped to computed using mapGetters and actions can be mapped to methods using mapActions as below example

// component.vue
// namespace_name=products

<template>
  <div>
    <p> This is awesome product {{getRecentProduct}} </p>
  </div>
  <button @click="onButtonClick()"> Clear recent</button>
</template>
<script>
import { mapGetters, mapActions } from "vuex";

export default {
  computed: {
    ...mapGetters({
        getRecentProduct: "products/getRecentProduct",
    }),
    anotherComputed(){
        return "anotherOne"
    }
  },
  methods: {
     ...mapActions({
        clearRecentProduct: "products/clearRecentProduct",
    }),
    onButtonClick(){
        this.clearRecentProduct(); /// Dispatch the action 
    },
    anotherMethods(){
        console.log(this.getRecentProduct); // Access computed props
    }
  }
};
</script>

Dipak Telangre
  • 1,792
  • 4
  • 19
  • 46
0

Here's how you can access vuex Getters & Mutations using Composition API (setup)

<script setup>
import { useStore } from 'vuex'

const store = useStore();

var value = store.getters['subModuleName/getterMethod'];

store.commit['subModuleName/MutationMethod'];

</script>
Mimina
  • 2,603
  • 2
  • 29
  • 21