Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Separating data in vuex

I need to store different entities in my vuex-store. For example Companies, Employees and Workplaces...

These entities are connected by ID-Arrays.

  • Company.employees is an array of UserIds
  • Employee.workplaces is a list of workplace ids
  • ...

I implemented it both ways I know:

  • as a single very big store
  • with store modules for every entity

The first approach is straightforward but quickly becomes very bloated. The second approach is very clean but data handling is difficult when I need data from 2 stores to fulfill a getter (for example: getWorkplacesByCompany)

What is the preferred way to store such data?

like image 233
Thomas Avatar asked Sep 22 '17 12:09

Thomas


3 Answers

Modular is definitely better. It avoids the bloat you mentioned and you can always access the data from other modules via the rootState or rootGetters options passed to the getter functions.

Here's an example:

const employees = {
  state: {
    employees: [
      { id: 1, name: 'Jeff' },
      { id: 2, name: 'Joe' },
      { id: 3, name: 'Jimmy' },
      { id: 4, name: 'Jake' },
      { id: 5, name: 'Jill' },
    ]
  },
}

const companies = {
  state: {
    companies: [
      { id: 1, name: 'Foo Co.', employeeIDs: [ 1, 4, 5 ] },
      { id: 2, name: 'Bar Co.', employeeIDs: [ 2, 3, 5 ] },
    ]
  },
  getters: {
    getCompanyEmployees(state, getters, rootState, rootGetters) {
      return (companyID) => {
        let company = state.companies.find((c) => c.id = companyID);        
        return rootState.employees.employees.filter((e) => {
          return company.employeeIDs.indexOf(e.id) >= 0;
        })
      }
    }
  }
}

const store = new Vuex.Store({
  modules: { employees, companies }
})

new Vue({
  el: '#app',
  store,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.4.0/vuex.min.js"></script>

<div id="app">
  {{ $store.getters.getCompanyEmployees(1) }}
</div>
like image 175
thanksd Avatar answered Oct 13 '22 06:10

thanksd


If you organize your modules and submodules logically, you can include getters at every level in your store based on where they need data from. So you might have stores and submodules as so:

App
  Blog
    Authors
    Posts
      Tags

The getter for getPostsByAuthor() would be in the Blog module because it needs data from both Authors and Posts, whereas the getter for getPostsByTag could be in the Posts module and the getter for getTagById could be directly in the Tag module.

like image 1
Jeff Avatar answered Oct 13 '22 04:10

Jeff


I'd say one store with namespaced modules is the right approach. You still have access to sibling modules. So in your getter you'd pass rootState as your third argument and access a sibling namespace like rootState.Employee.someData.

See more https://vuex.vuejs.org/en/api.html

like image 1
kano Avatar answered Oct 13 '22 05:10

kano