Skip to Content
HooksuseFetch

useFetch

useFetch is a lightweight data-fetching primitive with request parsing, abort handling, optional caching, and manual refetch support.

Live Example

Manual fetch flow

This demo shows a request you trigger on demand with refetch and abort controls.

Manual request flow

Fetch posts on demand

idle

This demo uses `enabled: false`, manual `refetch()`, and a short cache window. For more advanced query orchestration, use TanStack Query.

No request has been run yet.

Import

import { useFetch } from "react-rsc-kit/client";

Signature

const result = useFetch<T>(input, init?, options?);

Parameters

NameTypeDefaultDescription
inputRequestInfo | URL | null | undefinedrequiredRequest target. Use null or undefined to disable requests entirely.
initRequestInitundefinedFetch options such as method, headers, and body.
options.enabledbooleantrueRuns the request automatically when enabled.
options.initialDataT | nullnullInitial data before the first successful response.
options.cacheTimenumber0Cache lifetime in milliseconds. 0 disables caching.
options.cacheKeystring | nullderived for GET/HEADCustom cache key. Set null to disable caching for that request.
options.keepPreviousDatabooleantrueKeeps the last successful data visible while a new request is running.
options.parse(response: Response) => Promise<T>smart parserCustom response parser. Defaults to JSON for JSON responses, text for text responses, and Blob otherwise.

Returns

KeyTypeDescription
dataT | nullParsed response data.
errorError | UseFetchError | nullLast request error, including HTTP metadata for failed responses.
responseResponse | nullLast successful network response object.
status"idle" | "loading" | "success" | "error"Current request status.
statusCodenumber | nullLast HTTP status code seen by the hook.
loadingbooleanAlias for isFetching.
isFetchingbooleanWhether a request is currently in flight.
isIdlebooleanWhether no request has run yet.
isSuccessbooleanWhether the last request completed successfully.
isErrorbooleanWhether the last request ended in error.
refetch(options?: { ignoreCache?: boolean }) => Promise<T | null>Runs the request again. By default it bypasses cache.
abort() => voidAborts the active request.

Usage

"use client"; import { useFetch } from "react-rsc-kit/client"; type Post = { id: number; title: string; }; export function PostsList() { const { data, loading, error, refetch } = useFetch<Post[]>( "https://jsonplaceholder.typicode.com/posts", undefined, { cacheTime: 30_000, }, ); if (loading) return <p>Loading...</p>; if (error) return <p>{error.message}</p>; return ( <div> <button type="button" onClick={refetch}> Refetch </button> <ul> {(data as Post[]).slice(0, 5).map((post) => ( <li key={post.id}>{post.title}</li> ))} </ul> </div> ); }

Notes

  • useFetch is intentionally small and stays close to the native fetch model.
  • refetch() bypasses cache by default, which is usually what you want for manual refresh buttons.
  • Use parse when the response is not JSON or when you want custom decoding.
  • For advanced caching, retries, background refetching, mutations, pagination, or invalidation, use TanStack Query.
Last updated on