Query caching and HTTP mocks
Keep caching, retries and framework lifecycle in TanStack Query or SWR. The client handles typed
requests and responses. The runnable recipes use a small catalog schema
and are covered by actual TanStack Query, SWR hooks and MSW interception tests in pnpm test.
Install your chosen integration as an application dependency:
pnpm add @tanstack/react-query
# or
pnpm add swr
pnpm add -D mswThe shared operation factory in these recipes uses the optional @openapi-chain/query package
(pnpm add @openapi-chain/query). It snapshots JSON inputs and exposes both TanStack options and
SWR fetchers without framework dependencies. See the
adapter API and constraints. Local source/tarball verification does
not imply registry availability.
React is a peer dependency of the React integrations. The library core does not depend on any of
these packages. The examples import repository source; use openapi-chain and
@openapi-chain/query in your application and generate your own paths type. These recipes use
core-compatible JSON operations; the same pattern works with a metadata-backed strict client.
TanStack Query
The TanStack recipe builds queryOptions from a typed
operation. Include every data-affecting input in the key and forward the query function's signal
through init.signal.
const queries = catalogQueries(api, 'production:catalog:account-123');
const options = queries.detail({ id: 'book', locale: 'en' });
// Inside a component under QueryClientProvider:
const { data, error } = useQuery(options);
// Or outside React:
const item = await queryClient.fetchQuery(options);The cache scope must distinguish servers, tenants and accounts that can return different data for
the same operation. Use a non-secret identity, not an access token. Replace the scope or clear the
cache when authorization context changes, including permission changes within one account. Path
parameters, query parameters and representation choices belong in the key. Do not include
AbortSignal, callbacks or arbitrary RequestInit objects.
Use the default throwOnError: true: HTTP failures then enter the query library's error state as
HttpError. A throwOnError: false client resolves unsuccessful HTTP results; explicitly unwrap
and throw those results before using it as a fetcher. Network, cancellation and parsing failures
still reject independently of HTTP status.
Mutations are explicit. After an update, choose the affected queries to invalidate:
const mutation = useMutation({
...queries.update(),
onSuccess: () => queryClient.invalidateQueries({ queryKey: queries.prefix }),
});
mutation.mutate({ id: 'book', label: 'Updated' });Configure retry policy in TanStack Query; do not add a second automatic retry layer to the client. Only classify operations as queries when their application semantics permit caching and re-fetching. The HTTP method alone is not enough to infer mutation safety.
SWR
The SWR recipe returns a key and a typed fetcher. The input in the key drives the request. A null input disables the query:
const detail = catalogSWR(api, 'production:catalog:account-123');
const options = detail(selectedId ? { id: selectedId, locale: 'en' } : null);
const { data, error } = useSWR(options.key, options.fetcher);Provide the same scope isolation as in TanStack Query. Use SWR's mutation/revalidation APIs after writes. SWR does not supply TanStack's query-function cancellation signal in this recipe; it does not promise automatic fetch abortion on unmount. Application-managed cancellation requires a separately managed controller.
MSW
Mock at the HTTP boundary so the real client still performs URL construction, serialization and
response parsing. Share handlers between Node setupServer
and browser setupWorker.
import { setupServer } from 'msw/node';
import { handlers } from './handlers.js';
const server = setupServer(...handlers);
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());Use an absolute API URL in Node handlers. Browser setup additionally requires MSW's generated
service worker and await worker.start() before starting application requests. Keep handlers and
worker setup in development/test entry points. Do not include them in the production client bundle.
For strict-specific form styles, trailing slashes and multipart encoding, assert the received URL, headers and body in handlers. Keep an independent real HTTP test as well: interception is not evidence for CORS, redirects, streaming behavior or browser cookies.
References: TanStack query keys, cancellation, SWR arguments, MSW getting started.
