Utilizing the Vuetify v-skeleton-loader
component to wrap a v-data-table
component.
The server-side pagination and sorting in the data-table
component are set up.
To enable server-side pagination, the documentation recommends monitoring the options
object of the data-table
and making a new API call when the options change.
I have implemented setting state.loading = true
in my store module before initiating the API request and reverting it to state.loading = false
once the response is stored in the state.
The :loading
prop of the data-table
component is then used to access this state.
This setup works as intended on its own.
However, when I enclose the data-table
in a v-skeleton-loader
with the prop :loading="loading"
, it results in an endless loop of API requests and rendering of the skeleton-loader
.
I suspect that after the request is completed and state.loading = false
is triggered, the skeleton-loader
unmounts while the data-table
mounts, triggering changes in the watched options and causing a new API request leading to state.loading = true
. This cycle repeats infinitely.
If my assumption is correct, how can this issue be resolved?
Here's a minimal example:
<template>
<div>
<v-card>
<v-skeleton-loader
:loading="loading"
transition="scale-transition"
height="500"
type="table"
>
<v-data-table
:headers="headers"
:items="orders"
:fixed-header="true"
:server-items-length="totalItems"
:options.sync="options"
>
</v-data-table>
</v-skeleton-loader>
</v-card>
</div>
</template>
<script>
...
export default {
data() {
return {
options: {},
...
}
},
watch: {
options: {
handler() {
this.getDataFromApi();
},
deep: true,
},
},
methods: {
getDataFromApi() {
// construct query using options
this.$store.dispatch("orders/getOrdersCustom", query);
},
computed: {
...mapGetters("orders", ["orders"]),
...mapGetters("orders", ["loading"]),
},
mounted() {
this.$store.dispatch("orders/getOrders");
}
}
</script>
And the store module:
const namespaced = true;
const state = {
orders: [],
loading: false,
};
const getters = {
loading: (state) => state.loading,
orders: (state) => state.orders.items,
};
const actions = {
getOrdersCustom({ commit }, query) {
commit("GET_ORDERS_REQUEST");
return orderService.getOrdersCustom(query).then(
(data) => commit("GET_ORDERS_SUCCESS", data),
(error) => commit("GET_ORDERS_FAILURE", error)
);
},
}
const mutations = {
GET_ORDERS_REQUEST(state) {
state.loading = true;
},
GET_ORDERS_SUCCESS(state, data) {
Vue.set(state.orders, "items", data["hydra:member"]);
state.data = data;
state.loading = false;
},
}