useFetch Basic Usage
Learn how to use the type-safe composables generated by the CLI.
What the CLI Generates
For an OpenAPI endpoint like this:
/pet/{petId}:
get:
operationId: getPetById
parameters:
- name: petId
in: path
required: true
schema:
type: integer
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'The CLI generates a type-safe wrapper:
// Generated: composables/useFetchGetPetById.ts
import type { GetPetByIdRequest, Pet } from '../../..'
import { useApiRequest, type ApiRequestOptions } from '../runtime/useApiRequest'
export const useFetchGetPetById = (
params: GetPetByIdRequest, // ✅ Type-safe from OpenAPI
options?: ApiRequestOptions<Pet>
) => {
// useApiRequest returns Nuxt's useFetch under the hood
return useApiRequest<Pet>(`/pet/${params.petId}`, {
method: 'GET',
...options
})
}Basic Usage
Use the generated composable in your components:
<script setup lang="ts">
// Type-safe composable generated by CLI
const { data: pet, pending, error } = useFetchGetPetById({ petId: 123 })
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else>
<h1>{{ pet.name }}</h1>
<p>Status: {{ pet.status }}</p>
</div>
</template>Nuxt useFetch Documentation
Generated composables wrap Nuxt's useFetch. For complete documentation on data, pending, error, refresh(), and standard options like immediate, watch, server, see:
What the CLI Adds
1. Lifecycle Callbacks
Add hooks to intercept and react to request lifecycle events:
<script setup lang="ts">
const { data: pet } = useFetchGetPetById(
{ petId: 123 },
{
// ⏱️ Before request
onRequest: ({ url, headers, query }) => {
console.log('Fetching from:', url)
return {
headers: {
...headers,
'X-Request-ID': crypto.randomUUID()
}
}
},
// ✅ On success (2xx response)
onSuccess: (pet) => {
console.log('Loaded pet:', pet.name)
showToast(`Welcome ${pet.name}!`, 'success')
},
// ❌ On error (4xx/5xx or network error)
onError: (error) => {
console.error('Failed to load pet:', error)
if (error.status === 404) {
showToast('Pet not found', 'error')
}
},
// 🏁 Always runs (success or error)
onFinish: ({ success, data, error }) => {
console.log('Request complete:', success ? 'success' : 'failed')
}
}
)
</script>2. Pick
Select specific fields from the response without transform:
<script setup lang="ts">
// Only get id, name, and status
const { data: pet } = useFetchGetPetById(
{ petId: 123 },
{
pick: ['id', 'name', 'status']
}
)
// data is Ref<{ id: number, name: string, status: string }>
</script>More Features
For additional features like transform, global headers, baseURL, and more, see Shared Features →
Examples with Callbacks
Simple GET Request
<script setup lang="ts">
const { data: pets } = useFetchGetPets(
{},
{
onSuccess: (pets) => {
console.log(`Loaded ${pets.length} pets`)
}
}
)
</script>POST Request with Success Callback
<script setup lang="ts">
const form = ref({ name: '', status: 'available' })
const { execute: createPet, pending } = useFetchCreatePet(
{ body: form.value },
{
immediate: false, // Nuxt option: don't execute on mount
onSuccess: (pet) => {
showToast(`Created pet: ${pet.name}`, 'success')
navigateTo(`/pets/${pet.id}`)
form.value = { name: '', status: 'available' }
},
onError: (error) => {
showToast(`Failed: ${error.message}`, 'error')
}
}
)
</script>
<template>
<form @submit.prevent="createPet">
<input v-model="form.name" placeholder="Pet name" />
<button type="submit" :disabled="pending">Create</button>
</form>
</template>Request Interception
<script setup lang="ts">
const { data: pets } = useFetchGetPets(
{},
{
onRequest: ({ headers, query }) => {
return {
headers: {
...headers,
'X-Client-Version': '1.0.0'
},
query: {
...query,
timestamp: Date.now()
}
}
}
}
)
</script>Error Handling with Callbacks
<script setup lang="ts">
const { data: pet, error } = useFetchGetPetById(
{ petId: 123 },
{
onError: (error) => {
// Handle specific error codes
if (error.status === 404) {
showToast('Pet not found', 'error')
navigateTo('/pets')
} else if (error.status === 401) {
showToast('Please login', 'error')
navigateTo('/login')
} else {
showToast('Something went wrong', 'error')
}
}
}
)
</script>Global Callback Control
The CLI also adds global callback control:
Skip Global Callbacks
<script setup lang="ts">
// Skip authentication for public endpoint
const { data: publicPets } = useFetchGetPublicPets(
{},
{
skipGlobalCallbacks: true // Don't apply global callbacks
}
)
</script>Learn more about global callbacks →
Type Safety
All parameters and responses are fully typed from your OpenAPI schema:
// ✅ Type-safe parameters
useFetchGetPetById({ petId: 123 }) // Valid
useFetchGetPetById({ petId: 'abc' }) // ❌ TypeScript error
// ✅ Type-safe response
const { data: pet } = useFetchGetPetById({ petId: 123 })
pet.value?.name // ✅ string (autocomplete works)
pet.value?.unknown // ❌ TypeScript errorNext Steps
- Nuxt useFetch: Official Nuxt Documentation - Complete reference for
useFetchoptions - Callbacks: Lifecycle Callbacks - Learn about all callback types
- Global Callbacks: Global Callbacks - Set up plugin-based callbacks
- Configuration: Configuration Options - All CLI options
