Skip to content

Commit 1e592a8

Browse files
committed
[docs] state/mutations
1 parent d332c43 commit 1e592a8

File tree

2 files changed

+34
-7
lines changed

2 files changed

+34
-7
lines changed

docs/en/mutations.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Mutations
22

3-
Vuex mutations are essentially events: each mutation has a **name** and a **handler**. The handler function always gets the entire state tree as the first argument:
3+
Vuex mutations are essentially events: each mutation has a **name** and a **handler**. The handler function will receive the state as the first argument:
44

55
``` js
66
import Vuex from 'vuex'
@@ -18,7 +18,7 @@ const store = new Vuex.Store({
1818
})
1919
```
2020

21-
Using all caps for mutation names is just a convention to make it easier to differentiate them from actions.
21+
Using all caps for mutation names is just a convention to make it easier to differentiate them from plain functions.
2222

2323
You cannot directly call a mutation handler. The options here is more like event registration: "When an `INCREMENT` event is dispatched, call this handler." To invoke a mutation handler, you need to dispatch a mutation event:
2424

@@ -89,8 +89,22 @@ const store = new Vuex.Store({
8989

9090
Whether to use constants is largely a preference - it can be helpful in large projects with many developers, but it's totally optional if you don't like them.
9191

92-
### On to Actions
92+
### Mutations Must Be Synchronous
93+
94+
One important rule to remember is that **mutation handler functions must be synchronous**. Why? Consider the following example:
9395

94-
So far, we've triggering mutations by manually calling `store.dispatch`. This is a viable approach, but in practice, we will rarely do this in our component code. Most of the time we will be calling [actions](actions.md), which can encapsulate more complex logic such as async data fetching.
96+
``` js
97+
mutations: {
98+
SOME_MUTATION (state) {
99+
api.callAsyncMethod(() => {
100+
state.count++
101+
})
102+
}
103+
}
104+
```
105+
106+
Now imagine we are debugging the app and looking at our mutation logs. For every mutation logged, we want to be able to compare snapshots of the state *before* and *after* the mutation. However, the asynchronous callback inside the example mutation above makes that impossible: the callback is not called yet when the mutation is dispatched, and we do not know when the callback will actually be called. Any state mutation performed in the callback is essentially un-trackable!
107+
108+
### On to Actions
95109

96-
Also, one important rule to remember: all mutation handlers must be **synchronous**. Any async operations belong in actions.
110+
Asynchronicity combined with state mutation can make your program very hard to reason about. For example, when you call two methods both with async callbacks that mutate the state, how do you know when they are called and which callback was called first? This is exactly why we want to separate the two concepts. In Vuex, we perform all state mutations in a synchronous manner. We will perform all asynchronous operations inside [Actions](actions.md).

docs/en/state.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@ The single state tree does not conflict with modularity - in later chapters we w
88

99
### Getting Vuex State into Vue Components
1010

11-
So how do we display state inside the store in our Vue components? Here's how:
11+
So how do we display state inside the store in our Vue components? Since Vuex stores are reactive, the simplest way to "retrieve" state from it is simply returning some store state from within a [computed property](http://vuejs.org/guide/computed.html):
12+
13+
``` js
14+
// in a Vue component definition
15+
computed: {
16+
count: function () {
17+
return store.state.count
18+
}
19+
}
20+
```
21+
22+
Whenever `store.state.count` changes, it will cause the computed property to re-evaluate, and trigger associated DOM updates.
23+
24+
However, this pattern causes the component to rely on the global store singleton. This makes it harder to test the component, and also makes it difficult to run multiple instances of the app using the same set of components. Ideally, we want to "inject" the store into child components from the root component. Here's how to do it:
1225

1326
1. Install Vuex and connect your root component to the store:
1427

@@ -52,7 +65,7 @@ So how do we display state inside the store in our Vue components? Here's how:
5265
}
5366
```
5467

55-
Note the special `vuex` option block. This is where we specify what state the component will be using from the store. For each property name, we specify a function which receives the entire state tree as the only argument, and then selects and returns a part of the state, or even computes derived state. The returned result will be set on the component using the property name.
68+
Note the special `vuex` option block. This is where we specify what state the component will be using from the store. For each property name, we specify a getter function which receives the entire state tree as the only argument, and then selects and returns a part of the state, or a computed value derived from the state. The returned result will be set on the component using the property name, just like a computed property.
5669

5770
In a lot of cases, the "getter" function can be very succinct using ES2015 arrow functions:
5871

0 commit comments

Comments
 (0)