Skip to content

useAsyncData

useAsyncData wraps an async fetcher function and exposes reactive data, loading, error, and reload state. It calls the fetcher automatically on component mount.

Signature

ts
function useAsyncData<T>(
  fetcher: () => Promise<T>,
  initialValue: T,
  opts?: { immediate?: boolean }
): {
  data: Ref<T>
  loading: Ref<boolean>
  error: Ref<string | null>
  reload: () => Promise<void>
}

Basic usage

ts
import { useAsyncData } from '@jetpack-labs/jetpack-ui'
import api from '@/axios'

const { data: shifts, loading, error, reload } = useAsyncData(
  () => api.get('/api/v1/shifts').then(r => r.data),
  []
)
vue
<template>
  <div v-if="loading"><Spinner /></div>
  <div v-else-if="error" class="text-danger text-sm">{{ error }}</div>
  <Table v-else :columns="columns" :rows="shifts" />
</template>

With initial value

The second argument is the initial value of data before the fetch completes. It must match the expected return type T:

ts
// data starts as null until the fetch resolves
const { data: report } = useAsyncData(
  () => api.get('/api/v1/reports/123').then(r => r.data),
  null
)

Deferred fetch

By default the fetcher is called on onMounted. Pass { immediate: false } to defer:

ts
const { data, loading, reload } = useAsyncData(
  () => api.get('/api/v1/production').then(r => r.data),
  [],
  { immediate: false }
)

// call reload() manually when needed
function fetchNow() {
  reload()
}

Reloading

The returned reload function re-runs the fetcher and resets loading and error:

vue
<template>
  <Button variant="ghost" size="sm" @click="reload">Refresh</Button>
</template>

Error handling

If the fetcher throws, error is set to the error message and data retains its previous value. The error is cleared on the next reload() call.

Return values

KeyTypeDescription
dataRef<T>The resolved data (or initialValue while loading)
loadingRef<boolean>true while the fetcher is running
errorRef<string | null>Error message string, or null if no error
reload() => Promise<void>Re-runs the fetcher

Private — Jetpack Labs internal use only