Vuex Module Communication Using Nuxt with Nuxt Property Decorators
Tags: vue, nuxt, vuex
Published: 2020-08-01 16:39:35

When working with nuxt-property-decorators or specifically vuex-module-decorators I found that It was not clear how to make it work with Nuxt.

One thing that I could not figure out was how to call actions or mutations from inside modules. In this example I did a simple flow:

`Component -> first module -> second module -> first module`

# First Module<a id="sec-1"></a>

The idea is that the component will get data from this module's state. And this module sets the data through a different module.

```javascript
// ~/store/first.js

 import {
  Module,
  VuexModule,
  VuexMutation,
  VuexAction,
} from 'nuxt-property-decorator'
import { second } from '~/store'
@Module({
  name: 'first',
  namespaced: true,
  stateFactory: true,
})
export default class First extends VuexModule {
  text = 'before update'

  @VuexMutation
  setText(val) {
    this.text = val
  }

  @VuexAction({ rawError: true })
  setTextSecond(val) {
    second.setText(val)
  }
}
```

You can also dispatch an action from inside a module using namespaces. To do so, add a third parameter to the dispatch function with `{ root: true }`

```javascript
@VuexAction({ rawError: true })
setTextSecond(val) {
  this.context.dispatch('second/setText', val, { root: true })
}
```

Note that I added an argument to `VuexAction` decorator. With `{ rawError: true }` I get the real error if something goes wrong inside my action function. Otherwise it will throw a generic error that can be confusing.

# Second Module<a id="sec-2"></a>

This module will set the first module's state by calling the mutation on that module. 

```javascript
// ~/store/second.js

import { Module, VuexModule, VuexAction } from 'nuxt-property-decorator'
import { first } from '~/store'
@Module({
  name: 'second',
  namespaced: true,
  stateFactory: true,
})
export default class second extends VuexModule {
  @VuexAction({ rawError: true })
  setText(val) {
    first.setText(val)
  }
} 
```

# Component<a id="sec-3"></a>

It works importing the store modules or by using the namespace

## Using namespace<a id="sec-3-1"></a>

```vue
// ~/pages/storetest.vue

<template>
  <div>text is: {{ text }}</div>
</template>

<script>
import { Vue, Component } from 'nuxt-property-decorator'
@Component
export default class StoreTestComponent extends Vue {
  beforeMount() {
    this.$store.dispatch('first/setTextSecond', 'after update')
  }

  get text() {
    return this.$store.state.first.text
  }
}
</script>
```

## Using Module as Class<a id="sec-3-2"></a>

```vue
// ~/pages/storetest.vue

<template>
  <v-container>
    <div>text is: {{ text }}</div>
  </v-container>
</template>

<script>
import { Vue, Component } from 'nuxt-property-decorator'
import { first } from '~/store'
@Component
export default class StoreTestComponent extends Vue {
  beforeMount() {
    first.setTextSecond('after update')
  }

  get text() {
    return first.text
  }
}
</script>
```

**Important note**: Remember that you have to export the module for this method to work

```javascript
// ~/utils/store-accessor.js

import { getModule } from 'nuxt-property-decorator'
import First from '~/store/first'
import Second from '~/store/second'

let first = null
let second = null

function initialiseStores(store) {
  first = getModule(First, store)
  second = getModule(Second, store)
}

export {
  initialiseStores,
  first,
  second,
}
```

```javascript
// ~/store/index.js

import { initialiseStores } from '~/utils/store-accessor'
const initializer = (store) => initialiseStores(store)
export const plugins = [initializer]
export * from '~/utils/store-accessor'

```