A Suspense resource turns asynchronous work into a synchronous-looking read: it returns cached data or throws the cache entry's promise or error. Build a keyed resource that deduplicates requests and a SuspenseData render wrapper that reads during render. React catches a thrown pending promise at the nearest <Suspense> boundary, shows its fallback, and retries after settlement.
function createSuspenseResource(loader: (key: unknown) => unknown): {
read(key: unknown): unknown;
preload(key: unknown): Promise<unknown>;
clear(key?: unknown): void;
};
function SuspenseData({
resource,
resourceKey,
children: (data: unknown) => React.ReactNode,
}): React.ReactNode;
const users = createSuspenseResource((id) => fetchUser(id));
users.read(42);
// First call starts one request and throws its promise.
// After fulfillment, read(42) returns the exact cached user.
<Suspense fallback={<p>Loading…</p>}>
<SuspenseData resource={users} resourceKey={42}>
{(user) => <Profile user={user} />}
</SuspenseData>
</Suspense>
Map, so primitives follow SameValueZero comparison and object keys match only the same reference.preload(key) starts or deduplicates work and always returns that entry's original promise, even after settlement.clear() clears all entries, while clear(undefined) deletes only the explicit undefined key.SuspenseData validates resource.read and its function child, then calls children(resource.read(resourceKey)) only when ready.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
A Suspense resource turns asynchronous work into a synchronous-looking read: it returns cached data or throws the cache entry's promise or error. Build a keyed resource that deduplicates requests and a SuspenseData render wrapper that reads during render. React catches a thrown pending promise at the nearest <Suspense> boundary, shows its fallback, and retries after settlement.
function createSuspenseResource(loader: (key: unknown) => unknown): {
read(key: unknown): unknown;
preload(key: unknown): Promise<unknown>;
clear(key?: unknown): void;
};
function SuspenseData({
resource,
resourceKey,
children: (data: unknown) => React.ReactNode,
}): React.ReactNode;
const users = createSuspenseResource((id) => fetchUser(id));
users.read(42);
// First call starts one request and throws its promise.
// After fulfillment, read(42) returns the exact cached user.
<Suspense fallback={<p>Loading…</p>}>
<SuspenseData resource={users} resourceKey={42}>
{(user) => <Profile user={user} />}
</SuspenseData>
</Suspense>
Map, so primitives follow SameValueZero comparison and object keys match only the same reference.preload(key) starts or deduplicates work and always returns that entry's original promise, even after settlement.clear() clears all entries, while clear(undefined) deletes only the explicit undefined key.SuspenseData validates resource.read and its function child, then calls children(resource.read(resourceKey)) only when ready.The full solution is part of Premium
Walkthrough, edge cases, complexity notes, and the runnable editor unlock with a Premium subscription.
Submissions are part of Premium
Unlock community code, comments, reactions, and framework-specific approaches.
Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.