1

So, I love the idea of VueX modules and separating my data out, as it makes it far easier to reason when there are large sets of data... but I hate having to refer to them as nested objects in the store's state.

This is how the module currently works:

contactData.js:

export const contactData = {
    state: {
        contactInfo: null,
        hasExpiredContacts: false
    },
    mutations: {
        updateContactInfo(state, data) {
            state.contactInfo = data;
        },
        updateExpired(state, data) {
            state.hasExpiredContacts = data;
        }
    }
}

store.js:

import Vue from 'vue';
import Vuex from 'vuex';

import { contactData } from './contactData.js';

Vue.use(Vuex);

export default new Vuex.Store({
    modules: { contactData },
    state: {
        otherData: null
    }
});

Which would return as:

store: {
    state: {
        contactData: {
            contactInfo: null,
            hasExpiredContacts: false
        },
        otherData: null
    }
}

Is there anyway to, instead, display it as the following, while still using a module?

store: {
    state: {
        contactInfo: null,
        hasExpiredContacts: false,
        otherData: null
    }
}
Derek
  • 289
  • 1
  • 4
  • 16
  • You can't. But the helpers allow using a namespace when mapping (state or getters) to (computed or methods of the) Vue instance. Have you seen it? – acdcjunior Mar 16 '18 at 18:35

2 Answers2

1

I'm not sure that flattening out all your state would necessarily be a great idea if the project grew larger, as you'd have to be wary of property name clashes.

However, ignoring that, you could perhaps create flat getters for all module state automatically. Since this just provides alternative access all actions and mutations will work in the normal way.

const modules = {
  contactData,
  user,
  search,
  ...
}

const flatStateGetters = (modules) => {
  const result = {}
  Object.keys(modules).forEach(moduleName => {
    const moduleGetters = Object.keys(modules[moduleName].getters || {}); 
    Object.keys(modules[moduleName].state).forEach(propName => {
      if (!moduleGetters.includes(propName)) {
        result[propName] = (state) => state[moduleName][propName]; 
      }
    })
  })
  return result;
}

export const store = new Vuex.Store({
  modules,
  getters: flatStateGetters(modules),
  state: {
    otherData: null
  }
})
Richard Matsen
  • 20,671
  • 3
  • 43
  • 77
  • Hmm... This might be worth looking into. I guess I really don't care what they look like in the store, I just don't want to have to call **this.$store.state.contactData.contactInfo** etc. every time I need to access the data. This isn't a huge problem for me specifically, but I'm currently nesting my modules with the Mixins they're used in and coming up with a name that makes sense for all of them as a group for other devs is kind of difficult. I'm not worried about the project growing too large, these are just small "scripts" inside a larger, non-Vue app, each one has a specific function. – Derek Mar 16 '18 at 22:17
0

Since there's no deep merge possible still in ES6/ES7, you can't do it like the way you want.


You need to make your own function or find a suitable library to deep merge the objects to make it work.

Here's a possible solution using lodash:

modules: { _.merge(contactData, { state: { otherData: null } } ) }
Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231