'How to use a wrapper component within a dynamic component

I'm trying to implement a global Loading Component in Vue. The component should behave as a wrapper to other components and controlling its display using a loading variable in my store(Pinia) and binding the updating of this variable to my fetch method.

Loading Wrapper:

<template>
  <div v-if="loading">
    <LoadingSpinner></LoadingSpinner>
  </div>
  <div v-else>
    <slot />
  </div>
</template>

<script lang="ts" setup>
  import { useSessionStore } from '@/store/sessionStore'
  import LoadingSpinner from '@/components/Base/LoadingSpinner.vue'
  import { storeToRefs } from 'pinia'

  const sessionStore = useSessionStore()

  const { loading } = storeToRefs(sessionStore)
</script>

Store:

export const useSessionStore = defineStore({
  id: 'store',
  state: (): State => ({    
    loading: false,
    requestsPending: 0,
  }),
  async showLoading() {
    this.requestsPending++
    if (!this.loading) {
      this.loading = true
    }
  },
  async doneLoading() {
    if (this.requestsPending >= 2) {
      this.requestsPending--
    } else {
      this.requestsPending = 0
      this.loading = false
    }
  }
})

fetch api:

const request = async <T, D>(
    url: string,
    method: string
): Promise<T> => {
  const sessionStore = useSessionStore()
  await sessionStore.showLoading()
  try {
    const data: RequestInit = {
      method,
    }
    const response = await doFetch(url, data)
    const json: Record<string, unknown> = await response.json()

    return json as T
  } catch (error) {    
    throw error
  } finally {
    await sessionStore.doneLoading()
  }
}

The component is behaving like it should when I use it with a single component, but if I try to wrap a dynamic component, declared within a router-view, I can see that the application keeps repeating get requests and never completing the loading process.

Router View:

<template>
<RouterView v-slot="{ Component }">
      <LoadingWrapper>
        <component :is="Component" />
      </LoadingWrapper>
</RouterView>
</template>

Any ideas on what am I doing wrong here?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source