DEV Community

Diego Rodriguez
Diego Rodriguez

Posted on

Vuex Module Communication Using Nuxt with Nuxt Property Decorators

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

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

// ~/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 }

@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

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

// ~/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

It works importing the store modules or by using the namespace

Using namespace

// ~/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

// ~/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

// ~/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,
}
// ~/store/index.js

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

Top comments (0)