I ran into a situation where I needed to re-fetch a Vue Apollo smart query while showing a loading indicator. At first, I thought the smart query's $apollo.queries.[QUERY_NAME].loading
property was surely the way to go. But for some reason, this property doesn't get updated when the $apollo.queries.[QUERY_NAME].refetch()
method gets called.
Anyway, this is how I was able to get it to work;
<template>
<div class="posts">
<template v-if="isFetchingPosts">
<div class="loading-indicator">Loading...</div>
</template>
<div v-for="post in posts" :key="post.id" class="post-item">
<h2 class="post-title">{{ post.title }}</h2>
<div class="post-content">{{ post.content }}</div>
</div>
<button type="button" :disabled="isFetchingPosts" @click="refetchPosts">
Re-fetch Posts
</button>
</div>
</template>
<script>
export default {
data() {
return {
posts: [],
isFetchingPosts: false
}
},
apollo: {
posts: {
query: gql`
query PostsQuery($offset: Int!, $limit: Int!) {
posts(offset: $offset, limit: $limit) {
id
title
content
}
}
`,
variables() {
return {
offset: 0,
limit: 50,
}
},
result({ loading }) {
this.isFetchingPosts = loading
},
}
},
methods: {
refetchPosts() {
this.$apollo.queries.posts.refetch()
}
}
}
</script>
The trick here is using the result
hook which receives an object with a loading
property as its first argument. This loading
properly indicates whether the query is loading or not. We then use the value to update the isFetchingPosts
variable defined in our data
method.
The loading
property in the object that gets passed to the result
hook gets updated when the query is loading for the first time and when the this.$apollo.queries.posts.refetch()
method gets called. Which is exactly what we want.
Alright then. That's it for this one. I have a feature implementation to finish.✌🏽