The Default Data Hook for Pages
useFetch
useFetch wraps useAsyncData and $fetch into one ergonomic call. Pass a URL and get back reactive data, pending, and error refs.
What you'll learn
- Call useFetch with a URL string and read the destructured refs
- Destructure data, pending, and error and bind them to the template
- Type the response by passing a generic to useFetch
useFetch is the workhorse of data fetching in Nuxt. It runs on the server during SSR, serializes
the result into the page payload, and gives you reactive state on the client.
Basic Usage
<script setup lang="ts">
interface Post {
id: number
title: string
}
const { data: posts, pending, error } = await useFetch<Post[]>('/api/posts')
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<ul v-else>
<li v-for="p in posts" :key="p.id">{{ p.title }}</li>
</ul>
</template> What You Get Back
data— a ref containing the response body (typed by the generic).pending— true while in flight.error— a ref with the error, or null on success.refresh()— call to manually refetch.status—'idle' | 'pending' | 'success' | 'error'.
Reactive URLs
Pass a function instead of a string and useFetch will re-run whenever the function’s dependencies
change:
<script setup lang="ts">
const route = useRoute()
const { data: user } = await useFetch(() => `/api/users/${route.params.id}`)
</script> Auto-Dedupe
Two components on the same page calling useFetch('/api/posts') will share one request — Nuxt
dedupes by URL plus options during a single server render.