gertqin / vuex-class-modules

Typescript class decorators for vuex modules
MIT License
194 stars 20 forks source link

Cannot read property 'state' of undefined #36

Closed alamhubb closed 3 years ago

alamhubb commented 4 years ago

This is not a bug, but a small problem I encountered myself, but I will encounter the cause of this problem, I think it may be due to

// register module (could be in any file)

This sentence is ambiguous, so please change it to

//suggest to write it in the store.js file'

When I write this code in the AppModule.ts file, I will be prompted Cannot read property 'state' of undefined

AppModule.ts file content

import {VuexModule, Module} from "vuex-class-modules"

@Module({generateMutationSetters: true})
export default class AppModule extends VuexModule {
  name:string = ''
}

// register module (could be in any file)
import store from "./index"
export const appModule = new AppModule({store, name: 'app'})

And when I write this code into '@plugins/store/index', everything works fine

import Vue from 'vue'
import Vuex from 'vuex'
import AppModule from "@/plugins/store/AppModule"
import TalkModule from "@/plugins/store/TalkModule"
import UserModule from "@/plugins/store/UserModule"

Vue.use(Vuex)

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

export const appModule = new AppModule({store, name: 'app'})
export const talkModule = new TalkModule({store, name: 'talk'})
export const userModule = new UserModule({store, name: 'user'})

export default store

I think the reason for this problem may be that you must instantiate the appModule before using it. If you write this paragraph in AppModule.ts, it will not be called, so you cannot instantiate the appModule object

bodograumann commented 4 years ago

This sounds like you have circular imports. If AppModule.ts is imported while loading index.ts, you cannot import index.ts in AppModule.ts. That would explain why store is undefined in AppModule.ts.

alamhubb commented 4 years ago

No, at first, I only imported index.ts in AppModule and did not import AppModule in index.ts, and then the error

Cannot read property 'state' of undefined

Later, I only import the appModule in index.ts to resolve this error message

alamhubb commented 4 years ago

The two pieces of code on the page are irrelevant, they are code fragments of two different periods

alamhubb commented 4 years ago

Cannot read property 'state' of undefined

Because the appModule object was not created before use

Looking at the first piece of code, you can see that it is not executed

export const appModule = new AppModule ({store, name: 'app'})

Because there is no place to call the AppModule.ts file, it will not execute, nor will it create an AppModule object, so this error will occur.

The first part of the code only declares this piece of code

export const appModule = New AppModule ({store, name: 'app'})

But it didn't execute

bodograumann commented 4 years ago

Of course you need to import the module that you create where you want to use it.

alamhubb commented 4 years ago
// user-module.ts
import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";

@Module
class UserModule extends VuexModule {
  // state
  firstName = "Foo";
  lastName = "Bar";

  // getters
  get fullName() {
    return this.firstName + " " + this.lastName;
  }

  // mutations
  @Mutation
  setFirstName(firstName: string) {
    this.firstName = firstName;
  }
  @Mutation
  setLastName(lastName: string) {
    this.lastName = lastName;
  }

  // actions
  @Action
  async loadUser() {
    const user = await fetchUser();
    this.setFirstName(user.firstName);
    this.setLastName(user.lastName);
  }
}

// register module (could be in any file)
import store from "path/to/store";
export const userModule = new UserModule({ store, name: "user" });

Since the two pieces of code in the document are linked together, it looks like they are in the same file, which will cause

export const userModule = new UserModule ({store, name: "user"});

Will not be called.

This document is misleading.

Therefore it is recommended to modify

// register module (could be in any file)

update

//write to the store/index.js file or other files that will be executed

bodograumann commented 4 years ago

Sorry, if you misunderstood, but imho this is clear enough. If you read on, you see that there is an explanation about “The module can then be used in vue components as follows:”, where you import the instance userModule explicitly. So if you decide to create that instance in a dedicated file, you will also import it from there, i.e. that file will be executed.

I guess, if you feel so strongly about it, you could add a PR, @qinkaiyuan.

What do you think @gertqin?

gertqin commented 4 years ago

I'm still not sure I completely understand your problem @qinkaiyuan.

But I agree with @bodograumann, the whole purpose of vuex-class-modules is that you import the instantiated module wherever you need to use it. Whether you have instantiated the module in the same file as the class declaration, e.g.

// UserModule.ts
import store from "path/to/store"
import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";

@Module
class UserModule extends VuexModule {
...
}

export const userModule = new UserModule({ store, name: "user" });

on in separate files like

// UserModule.ts
import { VuexModule, Module, Mutation, Action } from "vuex-class-modules";

@Module
export class UserModule extends VuexModule {
...
}

// register-modules.ts
import store from "path/to/store"
import { UserModule } from "path/to/UserModule.ts"
export const userModule = new UserModule({ store, name: "user" });

should not matter. But of course in the first example you would have to import UserModule.ts and in the second register-modules.ts for the code to have any effect.