Search code examples
javascriptvuejs2vuexnuxt.js

NuxtJS + Vuex — datas in the store


Using NuxtJS (a VueJS framework), I’m trying to get a bunch of datas from a REST API in a layout template (which can’t use the classic fech() or asyncData() methods).

So I'm using vuex and the nuxtServerInit() action. This way, I should be able to gather all the datas directly during the load of the app, regardless of the current page.

But I can’t get it to work.

Here’s my map.js file for the store:

import axios from 'axios'

const api = 'http://rest.api.localhost/spots'
 
export const state = () => ({
	markers: null
})

export const mutations = {
	init (state) {
		axios.get(api)
			.then((res) => {
				state.markers = res.data
			})
	}
}

export const actions = {
	init ({ commit }) {
		commit('init')
	}
}

And the index.js (that can fire the nuxtServerInit()):

export const state = () => {}

export const mutations = {}

export const actions = {
	nuxtServerInit ({ commit }) {
		// ??
		console.log('test')
	}
}

But I can’t get it to work. The doc says:

If you are using the Modules mode of the Vuex store, only the primary module (in store/index.js) will receive this action. You'll need to chain your module actions from there.

But I don’t know how I shall do this. How do I call an action defined in another module/file?

I tried to copy various example, but never got them to work ; this is the best I could come up with.

What did I missed? If needed, here’s the repo and the store folder

Thanks!


Solution

  • I ran into the same problem, a few weeks ago, and here is how I solved it:

    ======== CLASSIC MODE =========

    store/index.js

    import Vue from 'vue'
    import Vuex from 'vuex'
    import auth from './modules/auth'
    import auth from './modules/base'
    
    Vue.use(Vuex)
    
    export default () => {
      return new Vuex.Store({
        actions: {
          nuxtServerInit ({ commit }, { req }) {
            if (req.session.user && req.session.token) {
              commit('auth/SET_USER', req.session.user)
              commit('auth/SET_TOKEN', req.session.token)
            }
          }
        },
        modules: {
          auth,
          base
        }
      })
    }
    

    store/modules/auth.js

    const state = () => ({
      user: null,
      token: null
    })
    
    const getters = {
      getToken (state) {
        return state.token
      },
      getUser (state) {
        return state.user
      }
    }
    
    const mutations = {
      SET_USER (state, user) {
        state.user = user
      },
      SET_TOKEN (state, token) {
        state.token = token
      }
    }
    
    const actions = {
      async register ({ commit }, { name, slug, email, password }) {
        try {
          const { data } = await this.$axios.post('/users', { name, slug, email, password })
          commit('SET_USER', data)
        } catch (err) {
          commit('base/SET_ERROR', err.response.data.message, { root: true })
          throw err
        }
      },
      /* ... */
    }
    
    export default {
      namespaced: true,
      state,
      getters,
      mutations,
      actions
    }
    



    Please notice the lines commit('base/SET_ERROR', err.response.data.message, { root: true }), which calls the mutation in another module (called base). And the namespaced: true option, which is required for this to work.

    To learn more about namespacing in vuex modules, please refer to the documentation: https://vuex.vuejs.org/en/modules.html


    ======== MODULES MODE =========

    The new 'modules mode' makes this much easier. You can have all the files in one folder and 'namespaced = true' is not required anymore.
    Here is how the above files look in modules mode:

    store/index.js

    export const state = () => ({})
    
    export const actions = {
      async nuxtServerInit ({ commit }, { req }) {
        if (req.session.user && req.session.token) {
          commit('auth/SET_USER', req.session.user)
          commit('auth/SET_TOKEN', req.session.token)
        }
      }
    }
    

    store/auth.js

    const state = () => ({
      user: null,
      token: null
    })
    
    const getters = {
      getUser (state) {
        return state.user
      },
      getToken (state) {
        return state.token
      }
    }
    
    const mutations = {
      SET_USER (state, user) {
        state.user = user
      },
      SET_TOKEN (state, token) {
        state.token = token
      }
    }
    
    const actions = {
      async register ({ commit }, { name, slug, email, password }) {
        try {
          const { data } = await this.$axios.post('/users', { name, slug, email, password })
          commit('SET_USER', data)
        } catch (err) {
          commit('base/SET_ERROR', err.response.data.message, { root: true })
          throw err
        }
      }
    }
    
    export default {
      state,
      getters,
      mutations,
      actions
    }
    



    To learn more about modules mode in nuxtjs, please refer to the documentation:
    https://nuxtjs.org/guide/vuex-store/#modules-mode