Skip to content

useFetch-Like Composable

Returns the API response as Nuxt async data. Intended for data that requires reactive updates, e.g. when using data in templates.

Responses are cached in the Nuxt payload between calls for the same request – see Caching.

Supports every useAsyncData option.

Placeholder

useMyApiData is a placeholder. The composable is generated based on your API endpoint ID. For example, endpoint jsonPlaceholder generates useJsonPlaceholderData.

Return Values

  • data: result of the asynchronous function.
  • refresh/execute: function to refresh the data returned by the handler.
  • error: error object if data fetching failed.
  • status: string indicating the status of the data request:
    • idle: when the request has not started, such as:
      • when execute has not yet been called and { immediate: false } is set
      • when rendering HTML on the server and { server: false } is set
    • pending: the request is in progress
    • success: the request has completed successfully
    • error: the request has failed
  • clear: function to set data to undefined (or options.default() value if provided), set error to undefined, set status to idle, and mark pending requests as cancelled.

By default, Nuxt waits until a refresh is finished before it can be executed again.

Type Declarations

ts
export type SharedAsyncDataOptions<ResT, DataT = ResT> = ComputedOptions<Omit<SharedFetchOptions, 'payloadCache'>> & Omit<AsyncDataOptions<ResT, DataT>, 'watch'> & {
  /**
   * Serve a repeated request from the Nuxt payload instead of sending it again.
   *
   * @remarks
   * Set this to opt a single call out. The module option of the same name turns payload caching off
   * for the whole app.
   *
   * @default the `payloadCache` module option
   */
  payloadCache?: MaybeRef<boolean>
  /**
   * The key passed to `useAsyncData`. By default, will be generated from the request options.
   */
  key?: MaybeRefOrGetter<string>
  /**
   * Watch an array of reactive sources and auto-refresh the fetch result when they change.
   * Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`.
   */
  watch?: MultiWatchSources | false
}

export type UseApiDataOptions<T> = Pick<
  ComputedOptions<NitroFetchOptions<string>>,
  | 'query'
  | 'headers'
  | 'method'
  | 'retry'
  | 'retryDelay'
  | 'retryStatusCodes'
  | 'timeout'
> & Pick<
  NitroFetchOptions<string>,
  | 'onRequest'
  | 'onRequestError'
  | 'onResponse'
  | 'onResponseError'
> & {
  path?: MaybeRefOrGetter<Record<string, string>>
  body?: MaybeRef<string | Record<string, any> | FormData | null>
} & SharedAsyncDataOptions<T>

export type UseApiData = <T = unknown>(
  path: MaybeRefOrGetter<string>,
  opts?: UseApiDataOptions<T>,
  autoKey?: string,
) => AsyncData<T | undefined, NuxtError>

Caching

Payload caching is on by default; payloadCache: false turns it off. The cache option controls the browser's HTTP cache separately:

ts
const { data } = await useMyApiData('posts', {
  cache: 'no-store' // or 'default', 'reload', 'no-cache', 'force-cache', 'only-if-cached'
})

The cache option needs server.proxyMode set to 'passthrough', or the request sent from the client. The default 'wrapped' mode turns every call into a POST, and a POST is never served from the browser's HTTP cache.

TIP

See the caching guide for more information on caching.

Examples

Demo Setup

These examples assume that you have set up an API endpoint called jsonPlaceholder:

ts
export default defineNuxtConfig({
  modules: ['nuxt-api-party'],

  apiParty: {
    endpoints: {
      jsonPlaceholder: {
        url: 'https://jsonplaceholder.typicode.com'
      }
    }
  }
})

Basic

vue
<script setup lang="ts">
const { data, refresh, error, status, clear } = await useJsonPlaceholderData('posts/1')
</script>

<template>
  <div>
    <h1>{{ data?.title }}</h1>
    <button @click="refresh()">
      Refresh
    </button>
  </div>
</template>

Extended Example

vue
<script setup lang="ts">
const postId = ref(1)

const { data, pending, refresh, error } = await useJsonPlaceholderData('comments', {
  // Whether to resolve the async function after loading the route, instead of blocking client-side navigation (defaults to `false`)
  lazy: true,
  // A factory function to set the default value of the data, before the async function resolves - particularly useful with the `lazy: true` option
  default: () => ({
    title: ''
  }),
  // A function that can be used to alter handler function result after resolving
  transform: res => res,
  // Custom query parameters to be added to the request, can be reactive
  query: computed(() => ({
    postId: postId.value
  })),
  // Custom headers to be sent with the request
  headers: {
    'X-Foo': 'bar'
  }
})
</script>

<template>
  <div>
    <h1>{{ data?.title }}</h1>
    <button @click="refresh()">
      Refresh
    </button>
  </div>
</template>

Client Requests

WARNING

Authorization credentials will be publicly visible. Also, possible CORS issues ahead if the backend is not configured properly.

INFO

If Nuxt SSR is disabled, all requests are made on the client-side by default.

To fetch data directly from your API and skip the Nuxt server proxy, set the apiParty module option client to true:

ts
export default defineNuxtConfig({
  modules: ['nuxt-api-party'],

  apiParty: {
    endpoints: {
      // ...
    },
    client: true
  }
})

Now you can make client-side requests by setting the client option to true in the composable.

ts
const data = await $jsonPlaceholder(
  'posts',
  { client: true }
)
ts
const { data } = await useJsonPlaceholderData(
  'posts',
  { client: true }
)

INFO

Set the client module option to always to make all requests on the client-side.

Released under the MIT License.