use-fetch
Fetch typed data with a custom parse decoder.
| Package | @vizejs/composable/use-fetch |
| Own the source | vize lib pull composable:use-fetch |
| Runtime exports | useFetch |
| Gzip budget | 9472 B |
Minimal setup
Use a Vue 3.5+ project with Vue SFC compilation configured (see Vite+ integration).
vp install @vizejs/composable
Import the entry directly. Call lifecycle-bound utilities inside <script setup> so cleanup follows the component scope; consult the runtime contract for this entry's SSR and hydration behavior.
import { useFetch } from "@vizejs/composable/use-fetch";
Try it
Check for updates on request
Fetch JSON on demand with explicit loading, success and error states.
What to observe: Check for updates shows Checking… and then Latest version: 0.449.0.
immediate: false waits for execute(). Replace the data URL with your endpoint; timeoutMs, retry and abort() are available.
Compare the initial and interacted states


Copy the example
Save this complete SFC in your Vue project. Its public imports and source are the same ones executed in the preview.
<script setup lang="ts">
import { useFetch } from "@vizejs/composable/use-fetch";
// Replace the data URL with your API endpoint.
const endpoint = `data:application/json,${encodeURIComponent('{"latest":"0.449.0"}')}`;
const { data, status, execute } = useFetch<{ latest: string }>(endpoint, { immediate: false });
</script>
<template>
<div class="composable-example">
<p>Fetch JSON when the reader asks, and show loading, result and error states.</p>
<button type="button" :disabled="status === 'pending'" @click="() => execute()">
Check for updates
</button>
<output aria-live="polite">{{
status === "success"
? `Latest version: ${data?.latest}`
: status === "error"
? "Could not check for updates."
: status === "pending"
? "Checking…"
: "Not checked yet."
}}</output>
</div>
</template>
Runtime contract
| Utility | Category | Stability | SSR | Hydration | Cleanup | Targets | Host globals | Uses |
|---|---|---|---|---|---|---|---|---|
useFetch |
networking | experimental | deterministic-fallback | caller-managed | caller, reactive-scope | web, server, worker, native, desktop, terminal | AbortController, DOMException, globalThis, window |
retryAsync, tryOnScopeDispose |
API
useFetch
Fetch typed data with a custom parse decoder.
function useFetch<Data>( url: MaybeRefOrGetter<string | URL | null | undefined>, options: UseFetchOptions<Data> & { readonly parse: (response: Response) => Promise<Data> }, ): FetchControls<Data>
useFetch
Fetch a non-JSON body whose type follows responseType.
function useFetch<const Kind extends Exclude<FetchResponseType, "json">>( url: MaybeRefOrGetter<string | URL | null | undefined>, options: UseFetchOptions<FetchResponseTypeMap[Kind]> & { readonly responseType: Kind }, ): FetchControls<FetchResponseTypeMap[Kind]>
useFetch
Fetch JSON. Supply validate to narrow unknown to a checked type.
function useFetch<Data = unknown>( url: MaybeRefOrGetter<string | URL | null | undefined>, options?: UseFetchOptions<Data> & { readonly responseType?: "json" }, ): FetchControls<Data>
useFetch
Reactive, abortable, retrying fetch with typed decoding and interceptors. Latest wins: starting an execution aborts the pending one, which then settles as "superseded" without touching state. The pending request is aborted when the owning reactive scope stops; outside a scope the caller owns abort(). Automatic execution (initial and on reactive URL/init changes) only happens in a browser or with an explicit fetch, so server rendering performs no I/O unless you await execute() in onServerPrefetch; state then holds initialData and status "idle".
function useFetch<Data>( url: MaybeRefOrGetter<string | URL | null | undefined>, options: UseFetchOptions<Data> = {}, ): FetchControls<Data>
const id = ref(1);
const { data, error } = useFetch(() => `/api/users/${id.value}`, {
validate: isUser,
retry: 2,
timeoutMs: 5_000,
});
Types
FetchResponseTypeMap
Data type produced by each built-in FetchResponseType.
| Member | Type | Description |
|---|---|---|
json |
unknown |
Parsed JSON; narrow it with validate. |
text |
string |
Response text. |
blob |
Blob |
Binary body as a Blob. |
arrayBuffer |
ArrayBuffer |
Binary body as an ArrayBuffer. |
formData |
FormData |
Multipart or URL-encoded form body. |
FetchRequest
Request description passed through the beforeRequest interceptor.
| Member | Type | Description |
|---|---|---|
url |
string |
Resolved request URL. |
init |
RequestInit |
Request options (headers, method, body, ...). |
FetchBeforeRequestContext
Context supplied to the beforeRequest interceptor.
| Member | Type | Description |
|---|---|---|
url |
string |
Resolved request URL. |
init |
RequestInit |
Request options (headers, method, body, ...). |
signal |
AbortSignal |
Signal aborted when the execution is aborted, superseded, or times out. |
FetchAfterResponseContext
Context supplied to the afterResponse interceptor.
| Member | Type | Description |
|---|---|---|
request |
FetchRequest |
Request that produced the response. |
response |
Response |
Successful response. |
data |
Data |
Decoded, validated data. |
UseFetchOptions
Options for useFetch.
| Member | Type | Description |
|---|---|---|
init? |
MaybeRefOrGetter<RequestInit | undefined> |
Reactive request options. Changes trigger a refetch when refetch is on. |
fetch? |
FetchImplementation |
Fetch implementation. Passing one explicitly also enables automatic execution on the server. |
responseType? |
FetchResponseType |
Built-in body reader. Ignored when parse is supplied. |
parse? |
(response: Response) => Promise<Data> |
Custom body decoder. Throwing produces a "parse" failure. |
validate? |
(data: unknown) => data is Data |
Type guard applied to the decoded body. Rejection produces an "invalid" failure. Without it, JSON is trusted to match Data. |
immediate? |
boolean |
Execute as soon as a URL is available. Automatic execution only happens in a browser or when fetch is supplied explicitly. |
refetch? |
boolean |
Re-execute when the reactive URL or init changes. |
initialData? |
Data |
Data exposed before the first success and after reset-like failures. |
timeoutMs? |
number |
Abort the request after this many milliseconds ("timeout" failure). |
retry? |
number | FetchRetryOptions |
Retry count or full retry policy (see retryAsync). By default only network failures and HTTP 408, 429, and 5xx responses are retried. |
scheduler? |
TimeoutScheduler |
Timer host for timeouts and retry backoff. |
beforeRequest? |
( context: FetchBeforeRequestContext, ) => FetchRequest | false | void | Promise<FetchRequest | false | void> |
Inspect or rewrite the request before it is sent. Return a replacement request, nothing to keep it, or false to abort the execution. |
afterResponse? |
( context: FetchAfterResponseContext<Data>, ) => Data | void | Promise<Data | void> |
Observe or transform successful data before it is committed. |
onError? |
(failure: FetchFailure) => void |
Observe failures of the newest execution. |
FetchControls
Reactive state and controls returned by useFetch.
| Member | Type | Description |
|---|---|---|
data |
Readonly<ShallowRef<Data | undefined>> |
Data of the newest successful execution, or initialData. |
error |
Readonly<ShallowRef<FetchFailure | undefined>> |
Failure of the newest settled execution. |
status |
Readonly<Ref<FetchStatus>> |
Lifecycle status driven by the newest execution. |
response |
Readonly<ShallowRef<Response | undefined>> |
Response of the newest execution that reached the server. |
statusCode |
ComputedRef<number | undefined> |
HTTP status of response. |
pending |
ComputedRef<boolean> |
Whether an execution is pending. |
execute |
() => Promise<FetchResult<Data>> |
Run the request now, superseding any pending one. Never rejects. Await it in onServerPrefetch to fetch during server rendering. |
abort |
(reason?: unknown) => boolean |
Abort the pending execution. |