vuex-module-decorators icon indicating copy to clipboard operation
vuex-module-decorators copied to clipboard

Context of this changes in @MutationAction compared to other decorators

Open Juxsta opened this issue 4 years ago • 2 comments

State and module declaration everything works fine except for when accessing "this" inside of a MutationAction. When checking "this" inside of an action I get the following. image Which populates all properties as expected. However logging the context of "this" inside of a mutationAction yields state, getters, commit, dispatch, rootGetters and rootState instead of all of the properties of the class. image I am unable to access the state from a mutationAction and get undefined when trying to do so.

Juxsta avatar Jan 16 '20 19:01 Juxsta

I have noticed the same issue. It appears the types of this in a MutationAction still includes the state properties so there is a mismatch between what the decorator is doing and what the types are indicating. There is also no typesafe way of accessing this.state since it is defined as () => ThisType<any> | ThisType<any> which doesn't include any of the state properties of the module. This pretty much renders this decorator unusable for me. 😭

kawazoe avatar Mar 29 '20 23:03 kawazoe

For my purposes I wanted to find a better strongly typed solution than the one from @andrei-gheorghiu. It works as it indented to the degree that that it is possible. I did misuse getModule, but it does it uses it only once per store.

import {Module, MutationAction, VuexModule} from 'vuex-module-decorators'
import {getState} from '@/core/plugins/vuex.plugin'

declare type ConstructorOf<C> = {
  new (...args: any[]): C
}

export function getState<Module extends VuexModule>(
  moduleClass: ConstructorOf<Module>
) {
  const module = getModule(moduleClass)
  return <Property extends keyof Module>(
    property: Property
  ): Module[Property] => {
    return module[property] as Module[Property]
  }
}

// your store
@Module
export default class Store extends VuexModule {
  name: string = 'default'

  @MutationAction
  async handleThing(thing: string) {
    const currentName = storeState('name')
    const name = await changeName(currentName, thing)
    return {name}
  }
}

const storeState = getState(Store)

I hope it helps someone else in the meantime 👍

harm-less avatar Jan 25 '21 15:01 harm-less