Commit 4790e726 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'docs-fe-vuex-updates' into 'master'

Docs fe vuex updates

See merge request gitlab-org/gitlab-ce!18826
parents d198290c 6c9af2d1
...@@ -68,10 +68,10 @@ Often we need to provide data from haml to our Vue application. Let's store it i ...@@ -68,10 +68,10 @@ Often we need to provide data from haml to our Vue application. Let's store it i
You can use `mapState` to access state properties in the components. You can use `mapState` to access state properties in the components.
### `actions.js` ### `actions.js`
An action is a playload of information to send data from our application to our store. An action is a payload of information to send data from our application to our store.
An action is usually composed by a `type` and a `payload` and they describe what happened. An action is usually composed by a `type` and a `payload` and they describe what happened.
Enforcing that every change is described as an action lets us have a clear understanting of what is going on in the app. Enforcing that every change is described as an action lets us have a clear understanding of what is going on in the app.
In this file, we will write the actions that will call the respective mutations: In this file, we will write the actions that will call the respective mutations:
...@@ -87,7 +87,7 @@ In this file, we will write the actions that will call the respective mutations: ...@@ -87,7 +87,7 @@ In this file, we will write the actions that will call the respective mutations:
export const fetchUsers = ({ state, dispatch }) => { export const fetchUsers = ({ state, dispatch }) => {
dispatch('requestUsers'); dispatch('requestUsers');
axios.get(state.endoint) axios.get(state.endpoint)
.then(({ data }) => dispatch('receiveUsersSuccess', data)) .then(({ data }) => dispatch('receiveUsersSuccess', data))
.catch((error) => { .catch((error) => {
dispatch('receiveUsersError', error) dispatch('receiveUsersError', error)
...@@ -102,7 +102,7 @@ In this file, we will write the actions that will call the respective mutations: ...@@ -102,7 +102,7 @@ In this file, we will write the actions that will call the respective mutations:
export const addUser = ({ state, dispatch }, user) => { export const addUser = ({ state, dispatch }, user) => {
dispatch('requestAddUser'); dispatch('requestAddUser');
axios.post(state.endoint, user) axios.post(state.endpoint, user)
.then(({ data }) => dispatch('receiveAddUserSuccess', data)) .then(({ data }) => dispatch('receiveAddUserSuccess', data))
.catch((error) => dispatch('receiveAddUserError', error)); .catch((error) => dispatch('receiveAddUserError', error));
} }
...@@ -126,7 +126,7 @@ The component MUST only dispatch the `fetchNamespace` action. Actions namespaced ...@@ -126,7 +126,7 @@ The component MUST only dispatch the `fetchNamespace` action. Actions namespaced
The `fetch` action will be responsible to dispatch `requestNamespace`, `receiveNamespaceSuccess` and `receiveNamespaceError` The `fetch` action will be responsible to dispatch `requestNamespace`, `receiveNamespaceSuccess` and `receiveNamespaceError`
By following this pattern we guarantee: By following this pattern we guarantee:
1. All aplications follow the same pattern, making it easier for anyone to maintain the code 1. All applications follow the same pattern, making it easier for anyone to maintain the code
1. All data in the application follows the same lifecycle pattern 1. All data in the application follows the same lifecycle pattern
1. Actions are contained and human friendly 1. Actions are contained and human friendly
1. Unit tests are easier 1. Unit tests are easier
...@@ -149,7 +149,7 @@ import { mapActions } from 'vuex'; ...@@ -149,7 +149,7 @@ import { mapActions } from 'vuex';
}; };
``` ```
#### `mutations.js` ### `mutations.js`
The mutations specify how the application state changes in response to actions sent to the store. The mutations specify how the application state changes in response to actions sent to the store.
The only way to change state in a Vuex store should be by committing a mutation. The only way to change state in a Vuex store should be by committing a mutation.
...@@ -175,7 +175,7 @@ Remember that actions only describe that something happened, they don't describe ...@@ -175,7 +175,7 @@ Remember that actions only describe that something happened, they don't describe
state.isLoading = false; state.isLoading = false;
}, },
[types.REQUEST_ADD_USER](state, user) { [types.REQUEST_ADD_USER](state, user) {
state.isAddingUser = true; state.isAddingUser = true;
}, },
[types.RECEIVE_ADD_USER_SUCCESS](state, user) { [types.RECEIVE_ADD_USER_SUCCESS](state, user) {
state.isAddingUser = false; state.isAddingUser = false;
...@@ -183,12 +183,12 @@ Remember that actions only describe that something happened, they don't describe ...@@ -183,12 +183,12 @@ Remember that actions only describe that something happened, they don't describe
}, },
[types.REQUEST_ADD_USER_ERROR](state, error) { [types.REQUEST_ADD_USER_ERROR](state, error) {
state.isAddingUser = true; state.isAddingUser = true;
state.errorAddingUser = error; state.errorAddingUser = error;
}, },
}; };
``` ```
#### `getters.js` ### `getters.js`
Sometimes we may need to get derived state based on store state, like filtering for a specific prop. 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) 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)
This can be done through the `getters`: This can be done through the `getters`:
...@@ -213,7 +213,7 @@ import { mapGetters } from 'vuex'; ...@@ -213,7 +213,7 @@ import { mapGetters } from 'vuex';
}; };
``` ```
#### `mutations_types.js` ### `mutations_types.js`
From [vuex mutations docs][vuex-mutations]: From [vuex mutations docs][vuex-mutations]:
> 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. > 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.
...@@ -289,7 +289,7 @@ export default { ...@@ -289,7 +289,7 @@ export default {
``` ```
### Vuex Gotchas ### Vuex Gotchas
1. Do not call a mutation directly. Always use an action to commit a mutation. Doing so will keep consistency through out the application. From Vuex docs: 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. > 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.
...@@ -342,7 +342,7 @@ describe('component', () => { ...@@ -342,7 +342,7 @@ describe('component', () => {
}; };
// populate the store // populate the store
store.dipatch('addUser', user); store.dispatch('addUser', user);
vm = new Component({ vm = new Component({
store, store,
...@@ -352,6 +352,18 @@ describe('component', () => { ...@@ -352,6 +352,18 @@ describe('component', () => {
}); });
``` ```
#### Testing Vuex actions and getters
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
export default () => {};
```
[vuex-docs]: https://vuex.vuejs.org [vuex-docs]: https://vuex.vuejs.org
[vuex-structure]: https://vuex.vuejs.org/en/structure.html [vuex-structure]: https://vuex.vuejs.org/en/structure.html
[vuex-mutations]: https://vuex.vuejs.org/en/mutations.html [vuex-mutations]: https://vuex.vuejs.org/en/mutations.html
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment