Loading...
Error: {{ error.message }}
```
### With Options
```ts
const { data } = await useFetch('/api/posts', {
// Query parameters
query: { page: 1, limit: 10 },
// Request body (for POST/PUT)
body: { title: 'New Post' },
// HTTP method
method: 'POST',
// Only pick specific fields
pick: ['id', 'title'],
// Transform response
transform: (posts) => posts.map(p => ({ ...p, slug: slugify(p.title) })),
// Custom key for caching
key: 'posts-list',
// Don't fetch on server
server: false,
// Don't block navigation
lazy: true,
// Don't fetch immediately
immediate: false,
// Default value
default: () => [],
})
```
### Reactive Parameters
```vue
```
### Computed URL
```vue
```
## useAsyncData
For wrapping any async function:
```vue
```
### Multiple Requests
```vue
```
## Custom Fetchers: createUseFetch / createUseAsyncData
Factory macros that produce a fully typed custom composable with pre-defined options. Must be an **exported** declaration inside `app/composables/` (Nuxt injects dedup keys at build time).
```ts
// app/composables/useAPI.ts
export const useAPI = createUseFetch({
baseURL: 'https://api.nuxt.com',
// shared interceptors, headers, etc.
onResponseError({ response }) {
if (response.status === 401) navigateTo('/login')
},
})
```
```vue
```
**Default vs Override mode:**
```ts
// Plain object → options act as DEFAULTS (caller can override)
export const useAPI = createUseFetch({ baseURL: '/api', lazy: true })
// Function → options OVERRIDE caller's (enforce auth/baseURL)
export const useAPI = createUseFetch(callerOptions => ({
baseURL: 'https://api.nuxt.com', // always enforced
}))
```
Use the **function form** when you need `useNuxtApp()` (called in setup context, not module scope):
```ts
// app/composables/useAPI.ts
export const useAPI = createUseFetch(callerOptions => ({
$fetch: useNuxtApp().$api as typeof $fetch,
...callerOptions,
}))
```
`createUseAsyncData` works identically for wrapping arbitrary async functions:
```ts
// app/composables/useCachedData.ts
export const useCachedData = createUseAsyncData({
getCachedData(key, nuxtApp) {
return nuxtApp.payload.data[key] ?? nuxtApp.static.data[key]
},
})
```
> Replaces the old "don't await your custom `useFetch` wrapper" caveat — use these factories instead of hand-rolled wrappers.
## $fetch
For client-side events (form submissions, button clicks):
```vue
```
**Important**: Don't use `$fetch` alone in setup for initial data - it will fetch twice (server + client). Use `useFetch` or `useAsyncData` instead.
## Return Values
All composables return:
| Property | Type | Description |
| --------- | -------------------------------------------------- | ------------------------------------------------- |
| `data` | `Ref