how to get data from API in vuex using axios?
Data
hook needs to return synchronously. You have to add the loading to created
or mounted
and just add the properties to data / state, so reactivity is working.
The loading of the data with Axios needs to be triggerd with an action because it's asynch. Mutations need to run synchronous. I've added the initial loading in created
. (mounted
would also work.)
I've used the Vuex helper mapState
to map the state properties to the component. Using getters would also work but mapState
is easier to write.
Please have a look at the demo below or this fiddle.
Also uncomment the code below the Vuex version in the fiddle and comment the app above to see how Axios is working with-out Vuex for a better understanding.
const URL = 'https://jsonplaceholder.typicode.com/posts';
const store = new Vuex.Store({
state: {
posts: [],
loading: true
},
actions: {
loadData({
commit
}) {
axios.get(URL).then((response) => {
// console.log(response.data, this)
commit('updatePosts', response.data)
commit('changeLoadingState', false)
})
}
},
mutations: {
updatePosts(state, posts) {
state.posts = posts
},
changeLoadingState(state, loading) {
state.loading = loading
}
}
})
new Vue({
el: '#app',
computed: Vuex.mapState(['posts', 'loading']),
store,
created() {
//console.log(this.$store)
this.$store.dispatch('loadData') // dispatch loading
}
})
/*
//example with-out vuex
new Vue({
el: '#app',
data() {
return {
loading: true,
posts: [] // add posts here so reactivity is working, also undefined would be OK
}
},
created() {
//this.loading = true --> not needed already set in data
axios.get(URL).then((response) => {
// console.log(response.data, this)
this.posts = response.data
this.loading = false
})
}
})
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.js"></script>
<div id="app">
<div v-if="loading">
loading...
</div>
<div v-else>
<ul>
<li v-for="post in posts">
<h1>
{{post.title}}
</h1>
<p>
{{post.body}}
</p>
</li>
</ul>
</div>
</div>