Render the Page First, Fill the Data In Later
useLazyFetch & lazy true
Lazy variants resolve their promise on the client without blocking initial render. Great for below-the-fold or non-critical data.
What you'll learn
- Use useLazyFetch to skip the await on slow endpoints
- Show a skeleton state while pending is true
- Compare lazy behavior to default blocking useFetch
By default, useFetch blocks navigation until the data resolves — the page only paints when the
fetch finishes. For slow or non-critical data, switch to the lazy variant.
useLazyFetch
<script setup lang="ts">
// No await — the page renders immediately.
const { data, pending } = useLazyFetch('/api/slow')
</script>
<template>
<div v-if="pending">
<Skeleton />
</div>
<ResultList v-else :items="data" />
</template> Equivalent: lazy true
useLazyFetch(url) is sugar for useFetch(url, { lazy: true }). Pick whichever reads better at the
call site.
const { data, pending } = useFetch('/api/slow', { lazy: true }) When to Reach For It
- Below-the-fold widgets — recommendations, related posts, comments.
- Heavy aggregations where the rest of the page should not wait.
- Anywhere a skeleton state is acceptable UX.
Heads Up
With lazy fetches, data.value starts as null (or your default value), so guard your template
with v-if or pending. Errors still land in error.value — handle them the same way.