Nuxt.js: Accessing the store from an external file

Created on 1 Nov 2017  路  6Comments  路  Source: nuxt/nuxt.js

// ~/store/index.js
import Vuex from 'vuex';

export default () => new Vuex.Store({
    actions: {
        someAction() {
            //
        }
    }
});

// external js file
import store from '~/store';

export default class AuthService {
    static login() {
        store.dispatch('someAction');
    }
}

I get an error when app builds:

TypeError: __WEBPACK_IMPORTED_MODULE_2__store__.default.dispatch is not a function
    at AuthService.js:10
    at <anonymous>

How can I dispatch an action of vuex in an external js file (not vue component)?

This question is available on Nuxt.js community (#c1780)

Most helpful comment

@freevital
Try this

// @/store/index.js

let store

const initStore = () =>  {
  return store || (store = new Vuex.Store({
    actions: {
      someAction() {
          //
      }
    }
  }))
}

export default initStore
// external js file

import store from '@/store';

export default class AuthService {
    static login() {
        store().dispatch('someAction');
    }
}

All 6 comments

There is a tricky way but not recommend, you'd better do it inside component 馃樃

let store
if (process.browser) {
  window.onNuxtReady(({$store}) => {
    store = $store
  })
}

export default class AuthService {
    static login() {
        store.dispatch('someAction');
    }
}

@freevital
Try this

// @/store/index.js

let store

const initStore = () =>  {
  return store || (store = new Vuex.Store({
    actions: {
      someAction() {
          //
      }
    }
  }))
}

export default initStore
// external js file

import store from '@/store';

export default class AuthService {
    static login() {
        store().dispatch('someAction');
    }
}

You can also do this:

export default class AuthService {
  constructor(store) {
    this.store = store
  }
  login() {
    this.store.dispatch('someAction')
  }
}

This way, your AuthService can be used with any Vue.js project.

Be vary here if you use @kamwing suggestion. This can lead to memory leak issues.

As the same instance of the store will be shared between all users on server side. That can:

1) Increase your initial store through time significantly (and initial HTML page rendered, as state is embeded in the template)
2) Expose user sensitive data to people that are not suppose to see it

I would say, the best option is to use your file as plugin and have access to store there. Or pass in the reference to the store (as @Atinux wrote).

@Atinux but how do you get relevant store when countructuing instance of this service, without getting components involved?

I.e. I need to propagate some events from web socket to store (including whether it is connected or not). Every page sometimes needs that data, so I'd rather have it as a plugin and read from store in components.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

danieloprado picture danieloprado  路  3Comments

surmon-china picture surmon-china  路  3Comments

jaredreich picture jaredreich  路  3Comments

bimohxh picture bimohxh  路  3Comments

vadimsg picture vadimsg  路  3Comments