Vuex Action Enhancer Example
by ktsn
HTML
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<div id="app">
<button type="button" @click="fetchMessage">Fetch Message</button>
<p class="loading" v-show="loading">Loading...</p>
<p class="error" v-if="error">{{ error }}</p>
<ul class="messages">
<li v-for="m in messages">{{ m }}</li>
</ul>
</div>
JavaScript
function loadingEnhancer(action) {
return function enhancedAction(ctx, payload) {
ctx.commit('loading', payload)
return action(ctx, payload)
.then(
result => ctx.commit('success', {
result,
payload
}),
error => ctx.commit('error', {
error,
payload
})
)
}
}
// Mock ajax request to get a message
// It may fails with a error message
function getMessage() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() < 0.3) {
reject('Failed to fetch a message')
} else {
resolve('Random Number: ' + Math.floor(Math.random() * 100))
}
}, 1000)
})
}
const store = new Vuex.Store({
state: {
loading: false,
error: null,
messages: []
},
mutations: {
loading (state) {
state.loading = true
state.error = null
},
success (state, { result }) {
state.loading = false
},
error (state, { error }) {
state.loading = false
state.error = error
},
addMessage (state, { message }) {
state.messages.push(message)
}
},
actions: {
fetchMessage: loadingEnhancer((ctx, payload) => {
return getMessage().then(result => {
ctx.commit('addMessage', { message: result })
})
})
}
})
new Vue({
el: '#app',
store,
computed: Vuex.mapState([
'loading',
'error',
'messages'
]),
methods: Vuex.mapActions([
'fetchMessage'
])
})