Skip to main content

useResource

This module provides hooks for loading asynchronous resources with caching support. It exports three functions: useResource for async loading, useResourceSync for Suspense-based loading, and clearResourceCache for cache management.

Usage​

Import the hooks like so:

import {
useResource,
useResourceSync,
clearResourceCache,
} from "~lib/use-resource";

useResource​

An async resource loading hook that returns loading state and data. Resources are cached by their id to prevent redundant fetches.

Parameters​

NameTypeRequiredDescription
idstringYesUnique identifier for caching the resource
source() => Promise<T>YesAsync function that fetches the resource

Return Value​

NameTypeDescription
dataT | undefinedThe fetched data, or undefined while loading
errorError | undefinedAny error that occurred during fetching

Example​

import { useResource } from "~lib/use-resource";

type WeatherData = {
temperature: number;
condition: string;
};

const Widget = () => {
const { data, error } = useResource<WeatherData>({
id: "weather-data",
source: async () => {
const response = await fetch("https://api.example.com/weather");
return response.json();
},
});

if (error) {
return <div>Error: {error.message}</div>;
}

if (!data) {
return <div>Loading...</div>;
}

return (
<div>
<h1>{data.temperature}°</h1>
<p>{data.condition}</p>
</div>
);
};

useResourceSync​

A Suspense-based synchronous resource loading hook. This hook throws a promise when data is not yet available, which should be caught by a Suspense boundary. Resources are cached globally to persist across Suspense re-renders.

Parameters​

NameTypeRequiredDescription
idstringYesUnique identifier for caching the resource
source() => Promise<T>YesAsync function that fetches the resource
groupstringNoNames every load this call could start, such as every request to one URL. See Runaway loads.

Return Value​

NameTypeDescription
dataTThe fetched data (always available when hook returns)

Runaway loads​

The id must come out the same on every render. When the suspended render retries, it looks the data up by id, so an id built from a random value or the current time never finds what it loaded and starts another load instead, forever. A lazy useState initializer doesn't help, because React discards the state of a component that suspends before its first commit.

Pass a group to stop such a loop. Once several loads in one group have finished and gone unread for a while, useResourceSync throws an error naming the group instead of starting another. The name appears in that error, so keep secrets out of it. useFetch passes the URL without its query.

Example​

import { Suspense } from "react";
import { useResourceSync } from "~lib/use-resource";

type StockData = {
symbol: string;
price: number;
};

const StockPrice = () => {
const { data } = useResourceSync<StockData>({
id: "stock-data",
source: async () => {
const response = await fetch("https://api.example.com/stock");
return response.json();
},
});

// data is guaranteed to be available here
return (
<div>
<h1>{data.symbol}</h1>
<p>${data.price}</p>
</div>
);
};

const Widget = () => {
return (
<Suspense fallback={<div>Loading...</div>}>
<StockPrice />
</Suspense>
);
};

clearResourceCache​

A utility function to clear the global resource cache used by useResourceSync. This is useful for testing or when you need to force a re-fetch of cached resources.

Parameters​

This function takes no parameters.

Return Value​

This function returns void.

Example​

import { clearResourceCache, useResourceSync } from "~lib/use-resource";

// Clear the cache before fetching fresh data
clearResourceCache();

// Now useResourceSync will fetch fresh data instead of using cached values
const { data } = useResourceSync({
id: "my-resource",
source: fetchMyResource,
});

Choosing Between useResource and useResourceSync​

FeatureuseResourceuseResourceSync
Loading stateReturns undefined while loadingThrows promise (Suspense)
Error handlingReturns error propertyThrows error
Cache scopeComponent-level (useRef)Global (module-level)
Best forStandard async patternsSSG/Suspense contexts

See Also​

  • useFetch - For standard HTTP fetch operations
  • useAI - For interacting with AI chat services