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

How to use with nuxtServerInit #291

Open felixoi opened 4 years ago

felixoi commented 4 years ago

Hey, I'm using nuxt-property-decorator which just exports some stuff of this module. So I'm reporting it here, because i think it's not a question for the nuxt-property-decorator module. I've created this module (store/usermodule.ts):

import {
  Module,
  VuexAction,
  VuexModule,
  VuexMutation,
} from 'nuxt-property-decorator'
import type { Context } from '@nuxt/types'
import type { User } from '~/types/ore/user'

@Module({
  name: 'usermodule',
  stateFactory: true,
  namespaced: true,
})
export default class UserModule extends VuexModule {
  user: User | undefined = undefined

  @VuexMutation
  setUser(user: User) {
    this.user = user
  }

  @VuexAction({ commit: 'setUser', rawError: true })
  init({ $axios }: Context) {
    $axios.$get<User>('/api/users/@me').then((u: User) => {
      return u
    })
  }
}

And i want to call the init action on nuxtServerInit so i created this store/index.ts

import type { Store, ActionTree } from 'vuex'
import { initializeStores } from '~/utils/store-accessor'

const initializer = (store: Store<any>) => initializeStores(store)
export const plugins = [initializer]
export const actions: ActionTree<any, any> = {
  async nuxtServerInit({ dispatch }, { $axios }) {
    await dispatch('usermodule/init', { $axios })
  },
}

export * from '~/utils/store-accessor'

store-accessor:

import { Store } from 'vuex'
import { getModule } from 'nuxt-property-decorator'
import UserModule from '~/store/usermodule'

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

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

export { initializeStores, userStore }

When doing so I'm running into the following 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)

Without the dispatch to the usermodule everything is working fine. Whats the correct way of doing this?

binoysarker commented 3 years ago

i am also facing this problem

TokugawaTakeshi commented 2 years ago

Avoiding the duplicating, I'll post my instance here.


I am sorry for the question in issues. Before open this issue, I asked same question in StackOverflow and even did the contest. The only one answer does not contain the working solution.


According this answer on Stack overflow, below listing from the vuex-module-decorators official documentation

// @/store/index.ts
import Vuex from 'vuex'

const store = new Vuex.Store({
  /*
  Ideally if all your modules are dynamic
  then your store is registered initially
  as a completely empty object
  */
})

in the Nuxt case must be:

import Vue from "vue";
import Vuex, { Store } from "vuex";

Vue.use(Vuex);

export const store: Store<unknown> = new Vuex.Store<unknown>({});

But how to integrate the nuxtServerInit action is above methodology? In below listing of store/index.ts, the nuxtServerInit will not be called.

import Vue from "vue";
import Vuex, { Store } from "vuex";

Vue.use(Vuex);

export const store: Store<unknown> = new Vuex.Store<unknown>({
  actions: {
    nuxtServerInit(context: unknown): void {
      console.log("Called !");
      console.log(context);
    }
  }
});

Update

The David Bernal's solution works, but with warning:

WARN  Classic mode for store/ is deprecated and will be removed in Nuxt 3. 
import Vuex, { Store } from "vuex";

interface RootState {}
export const store = new Vuex.Store<RootState>({
  actions: {
    nuxtServerInit: () => {
      console.log("Hello nuxtServerInit");
    }
  }
});

const createStore = (): Store<RootState> => {
  return store;
};

export default createStore;