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

Error "[vuex] unknown action type:" in Nuxt, however I did all exactly according "Accessing modules with NuxtJS" documentation

Open TokugawaTakeshi opened this issue 5 years ago • 27 comments

Let me repeat: I did all according Accessing modules with NuxtJS explanations.

Store Module:

import { Action, Mutation, VuexModule, Module } from 'vuex-module-decorators';


@Module({
  stateFactory: true,
  name: "AUTHENTICATION__STORE_MODULE"
})
export default class AuthenticationStoreModule extends VuexModule {

  private _token: string | null = null;

  @Action
  public async signIn(formData: { userId: string, password: string }): Promise<void> {
    console.log("Called!");
    const token: string = await new Promise(
        (resolve: (token: string)=> void): void => {
          setTimeout(() => { resolve('mock-token'); }, 2000);
        });
    console.log(token);
  }

  // ...
}

TypeScript types validation is all right. However, await authenticationStoreModule.signIn(formData) does not work.

Component:

import { Vue, Component, Prop } from 'vue-property-decorator';
import VueReferencesInspector from '~/utils/VueReferencesInspector';

import { authenticationStoreModule } from "~/store/";

interface IElementUiForm extends Vue {
  validate: (validationResult: (valid: boolean)=> void)=> void;
}


@Component
export default class extends Vue {

  // ...

  private onSubmit(): void {

    // ...

      try {

        console.log('~~~');
        console.log(authenticationStoreModule);
        console.log(authenticationStoreModule.signIn(formData));

        await authenticationStoreModule.signIn(formData);
        this.$router.push('/admin');
      } catch (error) {
        this.dataIsBeingSubmittedNow = false;
      }
    });
  }
}

console.logs are;

image

As you see authenticationStoreModule and authenticationStoreModule.signIn are not undefined. However, console.log("Called!"); did not output, so action signIn has not been called.

📁Repro Project

Once npm install done,

  1. Execute npm run dev
  2. go to page http://localhost:3000/admin/login
  3. Try to login

You will see same console errors as in image.

TokugawaTakeshi avatar Sep 18 '19 09:09 TokugawaTakeshi

Try:

@Module({
  name: 'auth',
  stateFactory: true,
  namespaced: true,
})

For Nuxt usage you should match the filename and namespace of your module, so this module should be in ~/store/auth.ts.

danielroe avatar Sep 22 '19 06:09 danielroe

Thank you for the answer. It works for me; you may close this issue.

For Nuxt usage you should match the filename and namespace of your module, so this module should be in ~/store/auth.ts.

Was I miss this in documentation, or it is not documented yet?

TokugawaTakeshi avatar Sep 23 '19 07:09 TokugawaTakeshi

Faced the issue as @TokugawaTakesi, so, @danielroe how we do namespace if my modules located under ~/store/modules/auth.ts?

avxkim avatar Nov 04 '19 12:11 avxkim

@webcoderkz Either move the module to ~/store/auth.ts, move it out of the ~/store directory entirely, or pass it the namespace modules/auth.

danielroe avatar Nov 04 '19 12:11 danielroe

Sorry, but where do we pass a custom namespace name?

Bottom of this page: https://github.com/championswimmer/vuex-module-decorators has an example for SSR usage (Nuxt), but there module is located under ~/store/modules/MyStoreModule.ts and they call it as usually, so there's an error in documentation?

avxkim avatar Nov 04 '19 12:11 avxkim

https://championswimmer.in/vuex-module-decorators/pages/advanced/namespaced.html

danielroe avatar Nov 04 '19 12:11 danielroe

I already read that, thanks. My question was - how to use getModule(moduleName, this.$store) inside a component with namespaces ~/store/modules/auth.ts

avxkim avatar Nov 04 '19 13:11 avxkim

@webcoderkz I believe the answer is there. In your case:

@Module({ namespaced: true, name: 'modules/auth' })

But I may be misunderstanding your question.

danielroe avatar Nov 04 '19 13:11 danielroe

my custom module (~/store/modules/settingsModule.ts):

import { Module, VuexModule } from 'vuex-module-decorators'

@Module({
  name: 'modules/settingsModule',
  namespaced: true,
  stateFactory: true
})
export default class settingsModule extends VuexModule {
  public test: string | undefined = process.env.CMS_URL
}

Using this module in a component:

public env = getModule(settingsModule, this.$store).test

Throws an error, Cannot read property 'test' of undefined

avxkim avatar Nov 04 '19 13:11 avxkim

@webcoderkz Hm, not sure. Can you share a repro?

FYI: I no longer use vuex-module-decorators but I'm very happy to take a look. :smiley:

danielroe avatar Nov 04 '19 13:11 danielroe

@danielroe why don't you use it anymore? There's better alternatives to it?

avxkim avatar Nov 04 '19 14:11 avxkim

@webcoderkz I think it's great - but I had to abandon because of this issue. However, a fix has now been merged and hopefully will be released soon. :smiley:

danielroe avatar Nov 04 '19 14:11 danielroe

@danielroe Do you have any example of the solution?

MisaelMa avatar Nov 10 '19 23:11 MisaelMa

@MisaelMa The solution to what?

danielroe avatar Nov 11 '19 07:11 danielroe

Same issue is here. I changed module name matching with file name and move @/store/modules/user.ts to @/store/user.ts. However it doesn't work...

mikinovation avatar Dec 21 '19 23:12 mikinovation

My code is here.

login.vue

import { createComponent, reactive } from '@vue/composition-api'
import { userStore } from '@/store'

....
setup() {
    const state = reactive<State>({
      email: '[email protected]',
      password: 'pass'
    })

    const login = () => {
      // eslint-disable-next-line no-console
      console.log('userStore', userStore)
      userStore.Login(state.email, state.password)
      // root.$router.push("/")
    }

    return {
      state,
      login
    }
  }
....

utils/store-accessor.ts

import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import { User } from '~/store/user'

// eslint-disable-next-line import/no-mutable-exports
let userStore: User

function initialiseStores(store: Store<any>): void {
  userStore = getModule(User, store)
}

export { initialiseStores, userStore }

mikinovation avatar Dec 21 '19 23:12 mikinovation

None of the solutions proposed here work for me either. I've recreated the issue in this repo:

https://github.com/qelix/nuxt-vuex-module-decorators-repro

Steps to reproduce:

  1. Clone repo, run yarn && yarn dev
  2. Open localhost:3000
  3. Open dev tools to find [vuex] unknown mutation type: test/setTest in console as proof that it doesn't work

Or just use Codesandbox: https://codesandbox.io/s/github/qelix/nuxt-vuex-module-decorators-repro

It is a simple reproduction of the issue, containing only a minimal configuration. I did everything according to the docs and the comments in this issue. Still can't get it to work, though.

Am I missing anything?

jpoep avatar Jan 09 '20 12:01 jpoep

It took me some trial and error, and the documentation & examples don't mention this at all, but it seems that you have to export default your module classes. See my minimal example that seems to work correctly.

woubuc avatar Feb 16 '20 21:02 woubuc

Thanks a lot dude, I just tested it in my project and it works like a charm!

Having to use default exports is kind of a letdown but it's still better than being forced to use the deprecated classic store mode.

jpoep avatar Feb 16 '20 23:02 jpoep

@danielroe I have my module in "module/home.ts" and I namespaced according to your suggestion and my namespace looks like:-

@Module({ namespaced: true, stateFactory: true, name: 'modules/home' })

But now I am not able to dispatch my action from this module

store.dispatch('modules/home/loadHome')

the action is not dispatching. Is there a way to dispatch my action inside "modules/home/loadHome"

akashlama1998 avatar Feb 18 '20 13:02 akashlama1998

@akashlama1998 As above, I recommend keeping your modules in the store folder if you are using Nuxt, because that is where Nuxt expects them.

I don't use this package any more, however, so apologies if that isn't of more help.

danielroe avatar Feb 19 '20 20:02 danielroe

@danielroe Its Ok.. Thanks for the reply.. I already moved my modules to ~/store.

akashlama1998 avatar Feb 20 '20 13:02 akashlama1998

I have documented some approaches to find out the optimum approach in this ticket: https://github.com/sniperadmin/qms-nuxt-ts/issues/17

sniperadmin avatar Jul 07 '20 22:07 sniperadmin

@webcoderkz I believe the answer is there. In your case:

@Module({ namespaced: true, name: 'modules/auth' })

But I may be misunderstanding your question.

thinks It bothered me for two hours

puzzle9 avatar Aug 15 '20 18:08 puzzle9

This might be the solution. For me exactly! Module name with namespace @/store/Vdp/main.ts

@Module({
  name: 'Vdp/main',
  namespaced: true,
  stateFactory: true
})
export default class main extends VuexModule {}

ceo-gazprom avatar Oct 16 '20 14:10 ceo-gazprom

Try:

@Module({
  name: 'auth',
  stateFactory: true,
  namespaced: true,
})

For Nuxt usage you should match the filename and namespace of your module, so this module should be in ~/store/auth.ts.

That solved my issue, but shouldn't this be in docs ? I could make a PR updating the readme

AllanPinheiroDeLima avatar Oct 26 '20 20:10 AllanPinheiroDeLima

[vuex] unknown local mutation type: signIn, global type: signin/signIn

// ~/store/signin.ts
import { Action, Module, Mutation, VuexModule } from 'vuex-module-decorators'

export const namespace = 'signin'

export interface SignInFormFields {
  email: string
  password: string
}

@Module({
  name: namespace,
  stateFactory: true,
  namespaced: true,
})
export default class SignIn extends VuexModule implements SignInFormFields {
  email = ''
  password = ''

  @Mutation
  public setEmail(email: string) {
    this.email = email
  }

  @Mutation
  public setPassword(password: string) {
    this.password = password
  }

  @Action
  signIn() {
    console.log('signIn action dispatched')
    return Promise.resolve({
      email: 'test',
    })
  }
}
// ~/pages/signin.vue
import { WrappedFormUtils } from 'ant-design-vue/types/form/form'
import { Component, namespace, Vue, Watch } from 'nuxt-property-decorator'
import {
  namespace as signInStoreNamespace,
  SignInFormFields,
} from '~/store/signin'

const SignInStore = namespace(signInStoreNamespace)

@Component({ layout: 'auth' })
export default class SignInFormFieldsPage extends Vue {
  form!: WrappedFormUtils

  @SignInStore.State((state: SignInFormFields) => state.email)
  public _email!: string

  @SignInStore.Mutation
  public setEmail!: (email: string) => void

  get email(): string {
    return this._email
  }

  @SignInStore.State((state: SignInFormFields) => state.password)
  public _password!: string

  @SignInStore.Mutation
  public setPassword!: (password: string) => void

  get password(): string {
    return this._password
  }

  @SignInStore.Mutation
  public signIn!: () => void

  handleSubmit(e: MouseEvent): void {
    e.preventDefault()
    this.form.validateFields((err) => {
      if (!err) {
        this.signIn()
      }
    })
  }
}

Mutations works fine but Actions don't

Pacheco95 avatar Jan 04 '21 11:01 Pacheco95