Vuex; the good parts
State, Actions, Getters, Mutations
Responsibilities in state management systems
Vue Components
Actions
State
Mutations
Backend API
Devtools
Dispatch
Commit
Mutate
Render
Vuex
single source of truth for store state
State
Actions
Mutations
Getters
similar to mutations but it commits mutations
the only way to change store state
to compute derived state based on store state.
(is cached)
(can only be sync)
(can be async)
Vending Machine Stock Counter
Vending Machine Stock Counter
Action
Restocking...
Mutation
40
const store = new Vuex.Store({
state: {
supply: 40
},
actions: {
restock(context) {
return context.commit('restock')
}
},
getters: {},
mutations: {
restock(state) {
state.supply--
}
}
})
new Vue({
el: "#vue",
computed: {
stock() {
return $store.state.supply
}
},
data() {
return {
stock: 40
}
},
methods: {
...
restock() {
$store.dispatch('restock')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
fetchFromInventory
stockItems
Let's rename!
const store = new Vuex.Store({
state: {
supply: 30
},
actions: {
fetchFromInventory(context) {
// make API Call
// on successful return, mutate
// i.e. context.commit("stockItems")
}
},
getters: {},
mutations: {
stockItems(state) {
// update supply
}
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return $store.state.supply
}
},
methods: {
...
restock() {
$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
// fake out API //
let inventory = {
"chips": {
stock: 40
}
}
var pingInventory = function(item) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(inventory[item]);
}, 3000);
});
}
const store = new Vuex.Store({
state: {
supply: 30
},
actions: {
fetchFromInventory(context) {
pingInventory("chips")
.then(inventory => {
context.commit('stockItems', inventory.stock)
})
}
},
getters: {},
mutations: {
stockItems(state) {
// update supply
}
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return $store.state.supply
}
},
methods: {
...
restock() {
$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
fake out an API
call fake API
...
var pingInventory = function(item) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(inventory[item]);
}, 3000);
});
}
const store = new Vuex.Store({
state: {
supply: 30
},
actions: {
fetchFromInventory(context) {
pingInventory("chips")
.then(inventory => {
context.commit('stockItems', inventory.stock)
})
}
},
getters: {},
mutations: {
stockItems(state payload) {
state.supply = payload
}
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return this.$store.state.supply
}
},
methods: {
...
restock() {
this.$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
// fake out API //
let inventory = {
"chips": {
stock: 40
}
}
var pingInventory = function(item) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(inventory[item]);
}, 3000);
});
}
const store = new Vuex.Store({
state: {
supply: 30,
isRestocking: false
},
actions: {
fetchFromInventory(context) {
context.commit('isRestocking', true)
pingInventory("chips")
.then(inventory => {
context.commit('stockItems', inventory.stock)
})
.finally(() => {
context.commit('isRestocking', false)
})
}
},
getters: {},
mutations: {
stockItems(state) {
// update supply
},
isRestocking(state, payload) {
state.isRestocking = payload;
}
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return this.$store.state.supply
},
isRestocking() {
return this.$store.state.isRestocking
}
},
methods: {
...
restock() {
$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
create a loading state
Exercise Time!
https://codepen.io/shortdiv/pen/xxGrMLV
Let's create isRestocking state in Vuex that gets toggled on fetchInventory
Vending Machine Stock Counter
Action
Dispensing...
Mutation
6
// fake out API //
let inventory = {
"chips": {
stock: 40
}
}
var pingInventory = function(item) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(inventory[item]);
}, 3000);
});
}
const store = new Vuex.Store({
state: {
supply: 30,
isRestocking: false
},
actions: {
fetchFromInventory(context) {
context.commit('isRestocking', true)
pingInventory("chips")
.then(inventory => {
context.commit('stockItems', inventory.stock)
})
.finally(() => {
context.commit('isRestocking', false)
})
}
},
getters: {},
mutations: {
stockItems(state) {
// update supply
},
isRestocking(state, payload) {
state.isRestocking = payload;
}
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return this.$store.state.supply
},
isRestocking() {
return this.$store.state.isRestocking
}
},
methods: {
...
restock() {
$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
single source of truth for store state
State
Actions
Mutations
Getters
similar to mutations but it commits mutations
the only way to change store state
to compute derived state based on store state.
(is cached)
(can only be sync)
(can be async)
Vending Machine Stock Counter
State
Getter
Changing how state is displayed
const store = new Vuex.Store({
state: {
supply: 40,
...
},
actions: {
fetchFromInventory(context) {
...
context.commit('stockItems', stock.inventory)
}
},
getters: {
isSupplyLow: state => state.supply < 10
},
mutations: {
stockItems(state, payload) {
state.supply = 40
},
...
}
})
new Vue({
el: "#vue",
computed: {
supply() {
return this.$store.state.supply
},
isSupplyLow() {
return this.$store.getters.isSupplyLow
}
},
methods: {
...
restock() {
$store.dispatch('fetchFromInventory')
}
},
template: `
<div>
<p class="supply">{{ supply }}</p>
<div class="actions">
<button @click="dispense">+</button>
<button @click="restock">-</button>
</div>
</div>
`,
})
Changing how state is displayed
ES
EN
Getter
Switch out the logic to switch language so it's handled in a Vuex getter
Exercise Time!
Vending Machine Stock Counter
Vuex Part 2
By shortdiv
Vuex Part 2
- 1,030