useFetch

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.

4 min read Level 2/5 #nuxt#useFetch
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.

useAsyncData →