To manage the state of an application you should use [Vuex][vuex-docs].
_Note:_ All of the below is explained in more detail in the official [Vuex documentation][vuex-docs].
## Separation of concerns
Vuex is composed of State, Getters, Mutations, Actions and Modules.
When a user clicks on an action, we need to `dispatch` it. This action will `commit` a mutation that will change the state.
_Note:_ The action itself will not update the state, only a mutation should update the state.
## File structure
When using Vuex at GitLab, separate this concerns into different files to improve readability:
```
└── store
├── index.js # where we assemble modules and export the store
├── actions.js # actions
├── mutations.js # mutations
├── getters.js # getters
├── state.js # state
└── mutation_types.js # mutation types
```
The following example shows an application that lists and adds users to the state.
(For a more complex example implementation take a look at the security applications store in [here](https://gitlab.com/gitlab-org/gitlab-ee/tree/master/ee/app/assets/javascripts/vue_shared/security_reports/store))
### `index.js`
This is the entry point for our store. You can use the following as a guide:
Sometimes we may need to get derived state based on store state, like filtering for a specific prop.
Using a getter will also cache the result based on dependencies due to [how computed props work](https://vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods)
> It is a commonly seen pattern to use constants for mutation types in various Flux implementations. This allows the code to take advantage of tooling like linters, and putting all constants in a single file allows your collaborators to get an at-a-glance view of what mutations are possible in the entire application.
```javascript
export const ADD_USER = 'ADD_USER';
```
### How to include the store in your application
The store should be included in the main component of your application:
```javascript
// app.vue
import store from 'store'; // it will include the index.js file
export default {
name: 'application',
store,
...
};
```
### Communicating with the Store
```javascript
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
1. Do not call a mutation directly. Always use an action to commit a mutation. Doing so will keep consistency throughout the application. From Vuex docs:
> why don't we just call store.commit('action') directly? Well, remember that mutations must be synchronous? Actions aren't. We can perform asynchronous operations inside an action.
Because we're currently using [`babel-plugin-rewire`](https://github.com/speedskater/babel-plugin-rewire), you may encounter the following error when testing your Vuex actions and getters:
`[vuex] actions should be function or object with "handler" function`
To prevent this error from happening, you need to export an empty function as `default`:
```
// getters.js or actions.js
// prevent babel-plugin-rewire from generating an invalid default during karma tests