Nuxt access store (in Module mode) from JS file
Asked Answered
S

3

6

I have an AuthService that I use in a namespaced store in my Nuxt app. I need to commit mutations from AuthService to the namespaced store but I can't figure out how to import the store into my AuthService.

I've seen examples where the store is imported into the JS file, but the store is explicitly defined in the Vue app. Because I'm using Nuxt with the Module mode for my store, I'm not sure of the root path where I can import my store into the AuthService file. As I understand it, Nuxt handles creating the root store and all the namespaced store behind the scenes when use "Module mode"

My Nuxt store directory includes index.js (which is empty) and auth.js which has the mutations I want to call from AuthService.

auth.js

import AuthService from '../firebase/authService'

const authService = new AuthService()

export const state = () => ({
  user: null
})

export const mutations = {
  setUser (state, user) {
    state.user = user
  }
}

export const actions = {
  async signUp ({ commit }, payload) {
    try {
      await authServices.createUser(payload)
      return Promise.resolve()
    } catch (err) {
      const notification = {
        duration: 5000,
        message: err.message,
        type: 'error'
      }
      commit('ui/activateNotification', notification, { root: true })
      return Promise.reject()
    }
  }
}

authService.js

import { fAuth, fDb } from './config'

// I think I need to import auth store here but I'm not sure how

export default class AuthClient {
  async createUser (payload) {
    try {
      const res = await fAuth.createUserWithEmailAndPassword(payload.email, payload.password)
      const { uid } = res.user
      const user = {
        ...payload,
        uid
      }
      await this._createUserDoc(user)
      this._initAuthListener()
      return Promise.resolve()
    } catch (err) {
      return Promise.reject(err)
    }
  }

  async _createUserDoc (user) {
    await fDb.collection('users').doc(user.uid).set(user)
  }

  _initAuthListener () {
    fAuth.onAuthStateChanged(async (user) => {
      try {
        if (user) {
          const userProfileRef = fDb.collection('users').doc(user.uid)
          const userProfileDoc = await userProfileRef.get()
          const { uid, userName } = userProfileDoc.data()

          // Here is where I want to call a mutation from the auth store

          this.store.commit('setUser', {
            uid,
            userName
          })
        } else {
          this.store.commit('setUser', null)
        }
      } catch (err) {
        console.log(err)
      }
    })
  }
}

Stated answered 14/2, 2020 at 1:55 Comment(1)
Did you finally find a solution ?Mediatory
C
6

I'd like to propose a solution using a plugin.

In the external module (externalModule.js) we define store variable and export an init function that receives Nuxt context as argument. The function assignes the store from context to the variable which can be now used in the module:

let store;
export function init (context) {
    store = context.store;
};
(...further business logic using store)

Then in the plugins folder we create a plugin file (let's call it storeInit.js). The file imports the init function from the external module and exports default plugin function required by Nuxt. The function receives context from Nuxt and we call the init function passing the context further:

import { init } from '[pathTo]/externalModule.js';
export default (context, inject) => {
    init(context);
};

Then we register the plugin in the nuxt.config.js file:

module.exports = {
    ...
    plugins: [
        { src: '~/plugins/storeInit' }
    ],
    ...
}

This way when the app is built by Nuxt and plugins are registered, the context object is passed to the external module and we can use anything from it, among others the store.

Coffee answered 25/8, 2021 at 12:38 Comment(1)
really nice solutionMidden
M
2

In index.js file which is in store folder you need to return store like this

import Vuex from 'vuex'
const createStore = () => {
  return new Vuex.Store({
    state: {
      counter: 0
    },
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore

and in your authService.js file you need to import store like this

import $store from '~/store'

by this you will be able to access your store

$store.commit('setUser', null)

I hope this works for you

Important Note: you don't need to install vuex because it is already shipped with nuxtjs

Mosasaur answered 5/11, 2020 at 7:24 Comment(1)
But will this not break Nuxt build process? Nuxt specifies how the store's index.js should look like and it expects it to export store's main properties (state, mutations, etc) from which it creates the store's instance. It does not expect an already created instance.Coffee
D
2

You can access as window.$nuxt.$store

Note: My nuxt version is 2.14.11

Donia answered 7/10, 2022 at 13:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.