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

state values not accessible in dynamic modules

Open vanhumbeecka opened this issue 7 years ago • 26 comments

I'd like to report a bug

Given the following code:

@Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState {
  token = 'something';

  @MutationAction({ mutate: [ 'roles', 'name', 'avatar' ] })
  async GetInfo(input: string) {
    log.debug(this.token)
    log.debug(input)
   ...
  }

When executing this MutationAction from outside the module, the logging of this.token returns undefined. However, If I pass the value from this module from outside this module as the input parameter, then I can get the correct value:

UserModule.GetInfo(UserModule.token).then(() => { ... }

So UserModule.token does provide the correct value, only you need to re-enter it in the module... which does not make much sense, but it's a workaround anyway.

I also observed that while debugging, the token value inside the Module can be accessed by using this.state.token instead of this.token. The only problem with this, is that typescript does not accept this as valid typings...

I don't know if this has something to do with dynamic modules or a more generic bug. Just leaving this here.

vanhumbeecka avatar Nov 25 '18 11:11 vanhumbeecka

Some extra info: Errors are also thrown on the MutationAction when he wants to set the roles (first param). This is essentially the same problem that module parameters (state params) are not found in these modules. So it's impossible to use the MutationAction with dynamic modules for now.

TypeError: Cannot read property 'roles' of undefined
    at Store.mutation (mutationaction.ts?6f5b:44)
    at wrappedMutationHandler (vuex.esm.js?2f62:697)
    at commitIterator (vuex.esm.js?2f62:389)
    at Array.forEach (<anonymous>)
    at eval (vuex.esm.js?2f62:388)
    at Store._withCommit (vuex.esm.js?2f62:495)
    at Store.commit (vuex.esm.js?2f62:387)
    at Object.boundCommit [as commit] (vuex.esm.js?2f62:335)
    at Store._callee4$ (mutationaction.ts?6f5b:28)
    at tryCatch (runtime.js?96cf:62)

vanhumbeecka avatar Nov 25 '18 12:11 vanhumbeecka

I'm having what looks like the same issue, in a static module.

Sounds just like https://github.com/championswimmer/vuex-module-decorators/issues/14 too, but this one was marked as fixed. I'm investigating on my side.

hectorj avatar Dec 11 '18 14:12 hectorj

Ok, the fix allowed to access getters in actions, not the state.

From what I understand this is not considered a bug: we should use getters in actions.

hectorj avatar Dec 11 '18 14:12 hectorj

I must have gotten something wrong: it isn't working for getters either in my MutationAction… still investigating

hectorj avatar Dec 11 '18 14:12 hectorj

@hectorj @vanhumbeecka ~~for me, this happens when I call an action inside another action. The second action won’t have access to this anymore.~~

Nevermind, this seems to always(?) happen. Will investigate further.


EDIT: Workaround

This syntax seems to work consistently for me:

(this.context.state as any).myStateValue

It’s not pretty, but it’s good enough until this is resolved.

FlorianWendelborn avatar Dec 21 '18 18:12 FlorianWendelborn

@vanhumbeecka Are you absolutely sure that you did not use stateFactory: true in your module? I just figured out that this breaks dynamic modules in my case (#85).

FlorianWendelborn avatar Jan 20 '19 22:01 FlorianWendelborn

@FlorianWendelborn nope, not using this at all. For now, I stopped using dynamic modules altogether. Only using namespaces modules. Works good so far.

vanhumbeecka avatar Feb 03 '19 12:02 vanhumbeecka

I'm having the same issue, and I don't find any elegant workaround. I don't get why we can't access the state within an action, in the vuex documentation this seems to be allowed.

Anyway, and as hectorj is mentionning, accessing the state within an action method using getters doesn't work either.

Kapcash avatar Mar 16 '19 16:03 Kapcash

I'm also facing the same issue right now. Any ideas @championswimmer? For comparison, I am not using dynamic modules, but I can't access anything in the getters for a MutationAction, only an Action

albernhagen avatar Apr 05 '19 19:04 albernhagen

Same issue here :+1:

JoshZA avatar May 23 '19 15:05 JoshZA

Same issue here, I can't access the state properties via moduleName.foo, only using moduleName.context.state.foo.

EDIT: A workaround is to use an internal state "internalFoo", and create a getter get foo() { return this.internalFoo } This will enable the autocompletion in typescript

Swiiip avatar Jun 28 '19 15:06 Swiiip

Same issue here. It would be good to get @championswimmer's take on this.

belvederef avatar Jul 01 '19 10:07 belvederef

Same issue here, I can't access the state properties via moduleName.foo, only using moduleName.context.state.foo.

EDIT: A workaround is to use an internal state "internalFoo", and create a getter get foo() { return this.internalFoo } This will enable the autocompletion in typescript

Careful about this approach! Although you will get autocompletion it messes with Vue reactivity and can cause unwanted bugs!

belvederef avatar Jul 09 '19 10:07 belvederef

I ran into maybe a similar issue and racked my brains for quite awhile until I figured it out.

vuex-module-decorators does not know if your module is namespaced or not and may get confused. That's what the namespaced option in the @Module decorator is for.

I think for 99% percent of use cases this should be set to true.

darylteo avatar Aug 01 '19 05:08 darylteo

Getting error, Same defination is there for other modules works fine but not sure what happen when try to access module .. State is always undefined. Please help !!!!

image

@Module({ dynamic: true, namespaced: true, store, name: 'measure' })
class MeasureModule extends VuexModule implements IUnitStore {
    u: Array<IUnit> = [];

    // getters
    get getUnits(): Array<IUnit> {
        return this.u;
    }

    @Mutation
    resetUnits() {
        this.u = [];
    }

    // mutations
    @Mutation
    setUnits(units: Array<IUnit>) {
        this.u = units;
    }

    // actions
    @Action({ rawError: true })
    async fetchAllUnits() {
        await get<IBlankRequest, IGetUnitsResponse>("", API.GET_ALL_UNITS).then(r => {
            this.setUnits(r.units);
            return r;
        });
    }

}
export default getModule(MeasureModule);

mayank30 avatar Apr 22 '20 20:04 mayank30

image

Why this is undefined, any specific reason

mayank30 avatar Apr 22 '20 20:04 mayank30

image

Why this is undefined, any specific reason

I don't see anything unusual in your code, maybe the issue is coming from somewhere else? E.g. preserveState is interfering? Also, in my experience if you do not surround your api calls with try...catch blocks vuex-module-decorator just breaks, it could be related.

belvederef avatar Apr 23 '20 09:04 belvederef

@belvederef your issues are most likely not due to try/catch, they’re probably because you don’t see the real error. I personally add rawError: true to the options of any @Action I use. Such a shame it’s not the default TBH. I think you should give this a try as it will show you the actual error so you can fix it.

FlorianWendelborn avatar Apr 23 '20 09:04 FlorianWendelborn

@FlorianWendelborn yes you are right, that was it. Not using try...catch or your suggested rawError: true makes it look like the error is coming internally from the store or the package when most times it is not. Since mayank30 is already using that, then it must be something else...

belvederef avatar Apr 23 '20 11:04 belvederef

't see anything unusual in your code, maybe the issue is coming from somewhere else? E.g. preserveState is interfering? Thank you for your reply on my comment I tried try catch in parent axios wrapper, and as suggested i tried on api call as well, Seems problem is with code, my code is working for other modules i have but not for module i am creating now, and onwards. Check try creating tax module its giving the same above error. image

mayank30 avatar Apr 24 '20 14:04 mayank30

are most likely not due to try/catch, they’re probably because you don’t see the real error. I personally add rawError: true to the options of any @Action I use. Such a shame it’s not the default TBH. I think you should give this a try as it will show you the actual error so yo

Thank for the comment, I tried rawError: true, problem is its is not able to find the state variable using this. and it returned as undefined and hence get the above error.

I spend lots of time debugg into the code but something was really fishy, which causes this problem

mayank30 avatar Apr 24 '20 14:04 mayank30

if you see the code i just use api call and from the response i want to add that into store object as simple as that. still store object is undefined image

mayank30 avatar Apr 24 '20 14:04 mayank30

Wait are you calling your action from a beforeRouteEnter hook? If so, that could be the reason of your problem. I am pretty sure this is not available inside beforeRouteEnter. Try calling it in mounted().

belvederef avatar Apr 24 '20 14:04 belvederef

preserveState: localStorage.getItem('vuex') !== null this is the problem, It was mentioned in docs only if want to persist the store object then user vuex-persist. but when i remove it it works fine.

mayank30 avatar Apr 24 '20 17:04 mayank30

Thank all of you guys for you help, I will find other way to store data in LocalStorage

mayank30 avatar Apr 24 '20 17:04 mayank30

preserveState: localStorage.getItem('vuex') !== null --> removal of this will miss to get the state on a fresh app re-load. @mayank30

haigopi avatar Oct 11 '21 19:10 haigopi