5
votes

I'm developing a small project and i want to be able to use namespaces to avoid getters, mutations, actions, with same names.

As described in docs, the modules must be imported to store, and maps must receive the path to the right module.

I can import everything by omitting the path, but it throws duplicate getter key, if i specify the path it throws module namespace not found in mapActions():

this errors happen in both getters and actions.

This is my store modules:

Stock.js

const state = {
    stocks: [
        {id: 1, name: 'BMW', price: 110},
        {id: 2, name: 'Google', price: 200},
        {id: 3, name: 'Apple', price: 250},
        {id: 4, name: 'Twitter', price: 8}
    ]
};
const getters = {
    getStocks: state => state.stocks
};
const mutations = {
    setStocks: (state, data) => state.stocks = data
};
const actions = {
    SETSTOCKS: (store, data) => {
        store.commit('setStocks', data)
    }
};

export default {
    namespace: true,
    state,
    getters,
    mutations,
    actions
};

StocksCopy.js

const state = {
    stocks: [
        {id: 1, name: 'Fiat', price: 110},
        {id: 2, name: 'Bing', price: 200},
        {id: 3, name: 'Microsoft', price: 250},
        {id: 4, name: 'Facebook', price: 8}
    ]
};
const getters = {
    getStocks: state => state.stocks
};
const mutations = {
    setStocks: (state, data) => state.stocks = data
};
const actions = {
    SETSTOCKS: (store, data) => {
        store.commit('setStocks', data)
    }
};

export default {
    namespace: true,
    state,
    getters,
    mutations,
    actions
}

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import stocks from './modules/stocks'
import stocksCopy from './modules/stocksCopy'

Vue.use(Vuex);

const debug = process.env.NODE_ENV !== 'production'

export default new Vuex.Store({
    namespace: true,
    state: {

    },
    getters: {

    },
    mutations: {

    },
    actions: {

    },
    modules: {
        stocks,
        stocksCopy,

    },
    strict: true,
});

Stocks.vue

<template>
    <div class="container">
        <div class="row">
            <button class="btn btn-primary" @click="setStocks({name: 'test', price: 100})">set stocks</button>
            <button class="btn btn-primary" @click="setStocksCopy({name: 'test', price: 100})">set stocksCopy</button>
        </div>
        <div class="row">
            <pre>Stocks: {{stocksList}}</pre>
        </div>
        <div class="row">
            <pre>StocksCopy: {{stocks}}</pre>
        </div>
        <div class="row">
            <app-stocks-stock v-for="(stock) in stocksList" :stock="stock"></app-stocks-stock>
        </div>

    </div>
</template>

<script>
    import { mapGetters, mapActions} from 'vuex'
    import Stock from './Stock.vue'
    export default {
        name: "Stocks",
        components: {
            'app-stocks-stock': Stock
        },
        computed: {
            ...mapGetters({
                stocksList: 'getStocks',
                stocks: 'stocks'
            })

        },
        data() {
            return {

            }
        },
        methods: {
            ...mapActions('stocksCopy', {
                setStocksCopy: 'SETSTOCKS'
            }),
            ...mapActions('stocks', {
                setStocks: 'SETSTOCKS'
            }),
        }
    }
</script>

<style scoped>

</style>

Errors:

[vuex] duplicate getter key: getStocks

[vuex] module namespace not found in mapActions(): stocksCopy/

2
it works for state but not for getters and actions this is the store in vue dev tools, {"stocks": {"stocks":[{"id":1,"name":"BMW","price":110},{"id":2,"name":"Google","price":200},{"id":3,"name":"Apple","price":250},{"id":4,"name":"Twitter","price":8}]}, "stocksCopy":{"stocks":[{"id":1,"name":"Fiat","price":110},{"id":2,"name":"Bing","price":200},{"id":3,"name":"Microsoft","price":250},{"id":4,"name":"Facebook","price":8}]}}Joel Rodrigues

2 Answers

12
votes

To use namespace, the right key is namespaced: true instead namespace: true

After you correct it, you can use paths like 'moduleName/getterName' or 'moduleName/actionName' in the functions mapGetters() or mapActions()

var { mapGetters, mapActions} = Vuex

const stock = {
	namespaced: true, // namespaced instead namespace
	state: {
	  stocks: [
    	{id: 1, name: 'BMW', price: 110},
	    {id: 2, name: 'Google', price: 200},
	    {id: 3, name: 'Apple', price: 250},
	    {id: 4, name: 'Twitter', price: 8}
    ]
	},
	getters: {
    getStocks: state => state.stocks
	},
	mutations: {
    setStocks: (state, data) => state.stocks = data
	},
	actions: {
    SETSTOCKS: (store, data) => {
    	console.log('SETSTOCK in stock')
      store.commit('setStocks', data)
    }
	}
}

const stockCopy = {
	namespaced: true, // namespaced instead namespace
	state: {
	  stocks: [
    	{id: 1, name: 'Fiat', price: 110},
      {id: 2, name: 'Bing', price: 200},
      {id: 3, name: 'Microsoft', price: 250},
      {id: 4, name: 'Facebook', price: 8}
    ]
	},
	getters: {
    getStocks: state => state.stocks
	},
	mutations: {
    setStocks: (state, data) => state.stocks = data
	},
	actions: {
    SETSTOCKS: (store, data) => {
      console.log('SETSTOCK in stockCopy')
      store.commit('setStocks', data)
    }
	}
}

const store = new Vuex.Store({
	modules: {
  	stock,
    stockCopy
  },
  strict: true,
})

window.main = new Vue({
	el:'#vue',
  store,
  computed: {
    ...mapGetters({
      stocksList1: 'stock/getStocks',  // moduleName/getterName
      stocksList2: 'stockCopy/getStocks'  // moduleName/getterName
    })
  },
  methods: {
    ...mapActions({
      setStocksCopy: 'stockCopy/SETSTOCKS', // moduleName/actionName
      setStocks: 'stock/SETSTOCKS' // moduleName/actionName
    }),
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
<div id="vue">
<button @click="setStocks({foo: 'bar'})">reset</button>
{{ stocksList1 }}
<hr>
<button @click="setStocksCopy({bar:'foo'})">reset</button>

{{ stocksList2 }}
</div>
0
votes

i think you forget to import your store in index file, so in your project go to store folder and then go to index file and import your module

import example from "./module-example"

and add example to modules

export default function (/* { ssrContext } */) {
  const Store = new Vuex.Store({
    modules: {
      // example
    },

where "example" is the name of your store, and the path of index file is

src/store/index.js