championswimmer / vuex-module-decorators

TypeScript/ES7 Decorators to create Vuex modules declaratively
https://championswimmer.in/vuex-module-decorators/
MIT License
1.8k stars 170 forks source link

ERR_STORE_NOT_PROVIDED with simple module #116

Open garyo opened 5 years ago

garyo commented 5 years ago

I have a simple module:

import { Module, VuexModule, Mutation, Action, MutationAction } from 'vuex-module-decorators'
import { User } from '../models'

@Module({namespaced: false, name: 'user'})
export default class UserModule extends VuexModule {
  user: User | null = null
  profile: Profile = {}

  @Mutation
  setUserM(user: User) {
    this.user = user
  }

  @Action({rawError: true})
  async setUser(user: User) {
    this.context.commit('setUserM', user)
  }
}

And I add it to my store non-dynamically:

const store = new Vuex.Store({
  modules: {
    UserModule
  },
})

But I get an error trying to invoke the action:

index.js?6fc5:234 Uncaught (in promise) Error: ERR_STORE_NOT_PROVIDED: To use getModule(), either the module
            should be decorated with store in decorator, i.e. @Module({store: store}) or
            store should be passed when calling getModule(), i.e. getModule(MyModule, this.$store)
    at value (index.js?6fc5:234)
    at getModule (index.js?6fc5:20)
    at Store.eval (index.js?6fc5:297)
    at step (index.js?6fc5:107)
    at Object.eval [as next] (index.js?6fc5:88)
    at eval (index.js?6fc5:81)
    at new Promise (<anonymous>)
    at __awaiter (index.js?6fc5:77)
    at Store.action (index.js?6fc5:289)
    at Array.wrappedActionHandler (vuex.esm.js?2f62:721)

I'm not calling getModule() anywhere; it seems the action itself is calling getModule(). How to fix this?

garyo commented 5 years ago

I ended up just using dynamic registration and the problem went away.

championswimmer commented 5 years ago

Yeah dynamic is recommended

On Fri 19 Apr, 2019, 6:28 PM GaryO, notifications@github.com wrote:

I ended up just using dynamic registration and the problem went away.

ā€” You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/championswimmer/vuex-module-decorators/issues/116#issuecomment-484888021, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKD7STY3UNPG4XVNXIVBR3PRG6XRANCNFSM4HGVXGNA .

IceSentry commented 5 years ago

I believe this would have worked too

const store = new Vuex.Store({
  modules: {
    user: UserModule
  },
})

You need to give the name to the module that is defined in the decorator

stephantabor commented 5 years ago

@IceSentry that does not currently work

goldingdamien commented 4 years ago

Yeah dynamic is recommended ā€¦ On Fri 19 Apr, 2019, 6:28 PM GaryO, @.***> wrote: I ended up just using dynamic registration and the problem went away. ā€” You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub <#116 (comment)>, or mute the thread https://github.com/notifications/unsubscribe-auth/AAKD7STY3UNPG4XVNXIVBR3PRG6XRANCNFSM4HGVXGNA .

@championswimmer What does this mean? Always?

alvaro-canepa commented 4 years ago

Is there any way to simple use vuex-class to run actions ?

And using less code, like this:

import { Vue, Component } from "vue-property-decorator";
import { Action } from "vuex-class";

@Component
export default class MyComp extends Vue {
  @Action("path/actionName") runActionName!: void;
}

Instead of this:

import { Vue, Component } from "vue-property-decorator";
import { getModule } from "vuex-module-decorators";
import MyStore from "@/store/mystore";

@Component
export default class MyComp extends Vue {
    loadingModule: MyStore | undefined;
    created() {
        this.loadingModule = getModule(MyStore, this.$store);
    }

    runActionName() {
        if (this.loadingModule) {
            this.loadingModule.actionName();
        }
    }
}

Thanks

alvaro-canepa commented 4 years ago

Found a solution, I don't know if is the best, but works...

Create a mixin

// /mixins/mymixin.ts
import { Vue, Component } from "vue-property-decorator";
import { getModule } from "vuex-module-decorators";
import MyStore from "@/store/mystore";

@Component
export default class MyMixin extends Vue {
    myModule: MyStore | undefined;

    created() {
        this.myModule = getModule(MyStore, this.$store);
    }

    runActionName(): void {
        if (this.myModule) {
            this.myModule.actionName();
        }
    }
}

Create component with mixin

// /components/mycom.vue
import { Component, Mixins } from "vue-property-decorator";
import MyMixin from "@/mixins/mymixin";

@Component
export default class MyComp extends Mixins(MyMixin) {
    mounted(){
        this.runActionName();
    }
}
gavinwyf commented 4 years ago

Is there any way to simple use vuex-class to run actions ?

And using less code, like this:

import { Vue, Component } from "vue-property-decorator";
import { Action } from "vuex-class";

@Component
export default class MyComp extends Vue {
  @Action("path/actionName") runActionName!: void;
}

Instead of this:

import { Vue, Component } from "vue-property-decorator";
import { getModule } from "vuex-module-decorators";
import MyStore from "@/store/mystore";

@Component
export default class MyComp extends Vue {
    loadingModule: MyStore | undefined;
    created() {
        this.loadingModule = getModule(MyStore, this.$store);
    }

    runActionName() {
        if (this.loadingModule) {
            this.loadingModule.actionName();
        }
    }
}

Thanks

I tried. But not working.

fgarit-te commented 4 years ago

Had the same problem. I am not using dynamic modules. I fixed my issue by removing the name property in @Module({namespaced: false, name: 'user'})

alvaro-canepa commented 4 years ago

https://github.com/Armour/vue-typescript-admin-template

This project is an excellent example of how to use vuex-module-decorators

dquinn40 commented 4 years ago

@fgarit-te That solution worked for me too. The namespace function then looks up the store module based on how you passed the name into the modules property inside store/index.ts file. If you want to use a different name then just remap it there.

dandry commented 4 years ago

The solution provided by @fgarit-te also works for me in a Nuxt TS project. If you define store modules as separate files in store directory, then the file name becomes the module name.

DimosthenisK commented 4 years ago

The solution provided by @fgarit-te also works for me in a Nuxt TS project. If you define store modules as separate files in store directory, then the file name becomes the module name.

How did you make that happen exactly? I get a "ERR_GET_MODULE_NAME" error: image

I use exactly the same method as described in the README, with the store accessor

UPDATE: It was nuxt-i18n. Make sure to disable it's vuex integration, it messes up with vuex-module-decorators!

chrispage1 commented 3 years ago

@fgarit-te thank you very much - worked for me!

@DimosthenisK - I suspect this is the root cause! Again, thank you šŸ‘

Ed1ks commented 3 years ago

I cant make it work in any way, neither do any of the examples work. This is definitely a bug. Cant get Vuex-Module-Decorators work. getModule() does not recognise the store in any way. Uncaught Error: ERR_STORE_NOT_PROVIDED: To use getModule(), either the module should be decorated with store in decorator, i.e. @Module({store: store}) or store should be passed when calling getModule(), i.e. getModule(MyModule, this.$store)

@championswimmer please take a look on this.

QuipHop commented 3 years ago

Facing same issues with enabled vuex in nuxt config, everything above doesn't work

sebastianhaberey commented 3 years ago

Stumbled across ERR_STORE_NOT_PROVIDED while looking for a way to access a module's action from inside another module's action. As mentioned above, the solution is to use dynamic modules. I still spent a lot of time on the details (I got ERR_GET_MODULE_NAME a lot) until I followed @alvaro-canepa's advice and had a look at https://github.com/Armour/vue-typescript-admin-template. So here are the essentials:

Start with emtpy store

// Store.ts
export default new Vuex.Store({ state: {} });

Declare dynamic module with name and namespaced

// ItemStore.ts
import Store from "@/store/Store";

@Module({ dynamic: true, store: Store, name: "ItemStore", namespaced: true })
class ItemStore extends VuexModule {

Retrieve module instantly and export it

// ItemStore.ts
export const itemStore = getModule(ItemStore); // initialized on application start rather than first use

Use module anywhere

import { itemStore } from "@/store/ItemStore";
await itemStore.load(id);
alvaro-canepa commented 3 years ago

@sebastianhaberey check the call of itemStore.load(id); if works fine outside vuex. I usually have this error and the issue is on the api call or server response.

tsiotska commented 3 years ago

Quickly figured out how to make it work with static module. Just get rid of "name" : @Module({ namespaced: true })