useResource
Loads data asynchronously and exposes it reactively.
Loads data asynchronously and exposes it reactively. Reading it while the first load is pending
holds the nearest <Suspense> boundary around the reader (not the creator) in its fallback;
reading it after a failure throws the error to the nearest error boundary. Refetching keeps the previous
value visible (state === "refreshing") and never re-suspends.
Two forms: useResource(fetcher) fetches once; useResource(source, fetcher) refetches whenever
source() changes and stays unresolved while it is false, null or undefined.
T is inferred from what the fetcher returns. info.value is typed unknown unless the
parameter is annotated: (info: ResourceInfo<User>) => ....
Source form of useResource: fetches for each value of source, and refetches whenever it
changes. While source() is false, null or undefined nothing is fetched and the resource
stays "unresolved" (or keeps its value, "ready"). A newer fetch aborts the previous one, whose
late result is ignored.
Import#
import { useResource } from "@shadow-js/core";
Signature#
function useResource<T>(
fetcher: (info: ResourceInfo) => T | Promise<T>,
options?: ResourceOptions<T>,
): Resource<T>
function useResource<S, T>(
source: Accessor<S | false | null | undefined>,
fetcher: (source: S, info: ResourceInfo) => T | Promise<T>,
options?: ResourceOptions<T>,
): Resource<T>
function useResource<S extends string | number | boolean | bigint | object, T>(
source: S,
fetcher: (source: S, info: ResourceInfo) => T | Promise<T>,
options?: ResourceOptions<T>,
): Resource<T>
function useResource<T>(
fetcher: (info: ResourceInfo<T>) => T | Promise<T>,
options?: ResourceOptions<T>,
): Resource<T>
function useResource<S, T>(
source: Accessor<S | false | null | undefined>,
fetcher: (source: S, info: ResourceInfo<T>) => T | Promise<T>,
options?: ResourceOptions<T>,
): Resource<T>
Parameters#
| Name | Description |
|---|---|
fetcher |
Called untracked, once at creation (skipped when a server render already provided the value) and again for every refetch(). It receives an abort signal, the refetching flag and the last value; it returns the value or a promise. |
options |
Initial value, server key and a devtools name. Undefined uses the defaults. |
source |
Tracked; its value is passed to fetcher. A plain value fetches once. |
fetcher |
Called untracked with the source value and the fetch info. |
options |
Initial value, server key and a devtools name. Undefined uses the defaults. |
Returns#
The resource (see Resource).
Throws#
- Nothing itself: a fetcher that throws or rejects makes the resource
"errored". Reading the resource then rethrows that error, so the nearest error boundary receives it. - Nothing itself. Reading the resource rethrows the error of a failed fetch.
Examples#
import { useResource } from "@shadow-js/core";
function Clock() {
const time = useResource(({ signal }) => fetch("/api/time", { signal }).then((r) => r.text()));
return <p>{time.loading ? "Loading..." : time()}</p>;
}
import { useResource, useSignal } from "@shadow-js/core";
function UserCard() {
const [id] = useSignal(1);
const user = useResource(id, (id, { signal }) =>
fetch(`/api/users/${id}`, { signal }).then((r) => r.json() as Promise<{ name: string }>),
);
return <p>{user()?.name}</p>;
}