Reputation: 658
Let's say in my Vue3 app I have a store whose state looks like this:
const store = {
state () => ({
items: []
}),
// ...
}
My App.vue has a single <router-view />
as its only template content.
Then I have an ItemList.vue
view which looks like this:
<template>
<div v-if="!loading">
<Item
v-for="item in items"
:key="item.id"
:item="item"
></Item>
</div>
<Skeleton v-else />
</template>
<script>
import Item from "...";
import Skeleton from "..."
import { mapState } from "vuex";
export default defineComponent({
name: "CourseList",
mixins: [loadingMixin],
components: {
Item, Skeleton
},
async created() {
this.loading = true
this.$store.dispatch("getItems", {
categoryId: this.$route.params.categoryId
})
this.loading = false
},
data() {
return {
loading: false,
};
},
computed: {
...mapState(["items"])
},
});
</script>
Essentially, the app allows you to navigate to URLs of the form categories/<id>/items
and retrieve items for that category. The items currently being viewed are stored in a flat array in the store. Every time the ItemList
component is created, an action is dispatched which simply makes an API call to the items endpoint for that category and saves the result in the store's state items
attribute. While this is happening, a skeleton is shown to the user.
The issue with this approach is that, while the user always gets fresh data because they are fetching the items every time they naviage to the view, there is also the inconvenience that if the data for the category hasn't changed, they are still going to be looking at the skeleton until the items are re-fetched.
If the user clicks a router-link and goes to another view that doesn't involve fetching items then comes back to the item list view for the same category as the last one they visited, I'd like them to not have to wait to see the data. I would still like the app to do the fetching, but display the existing data meanwhile. Of course, since I'm saving a single array of items, if the user goes to the list for another category, that data must not be displayed and the user must see the skeleton from the get go.
Can this be done in Vue? I tried using the <keep-alive>
component and giving it a :key
corresponding to the route's category id param but it didn't work.
Upvotes: 0
Views: 1083
Reputation: 385
If you know which categories user have visited, you can conditionally change loading
state, if not, create a set
in vuex
and keep previous categoryId
to it.
async created() {
if( the category has changed){
this.loading = true
}
this.$store.dispatch("getItems", {
categoryId: this.$route.params.categoryId
})
this.loading = false
}
Upvotes: 1