SWR
useStitchSWR runs a stitch as an SWR fetcher, so SWR owns caching and revalidation while the stitch stays typed, validated, and traced.
Use @stitchapi/swr when your app is already on SWR and
you want a stitch as the fetcher. SWR keeps owning caching, deduping, and
revalidation; the stitch stays the typed, validated, traced call. There is no
@stitchapi/query-core here — SWR is the store.
If you'd rather StitchAPI own the lifecycle directly — especially streaming,
which SWR doesn't model — reach for useStitchStream in
@stitchapi/react instead.
Example
Install the adapter alongside core, SWR, and React:
npm install @stitchapi/swr@rc stitchapi@rc swr reactstitchapi, swr, and react are peer dependencies.
useStitchSWR
Pass a stitch and its input; get SWR's own response back (data, error,
isLoading, isValidating, mutate). The cache key is the stitch's name plus the
input, so two components calling the same stitch with the same input dedupe to one
request.
import { useStitchSWR } from '@stitchapi/swr';
import { stitch } from 'stitchapi';
const getUser = stitch({
baseUrl: 'https://api.example.com',
path: '/users/{id}',
});
function Profile({ id }: { id: string }) {
const { data, error, isLoading } = useStitchSWR(getUser, {
params: { id },
});
if (isLoading) return <Spinner />;
if (error) return <Retry />;
return <h1>{data?.name}</h1>;
}Pass SWR options as the third argument — they go straight through:
useStitchSWR(getUser, { params: { id } }, { refreshInterval: 5000 });Conditional fetching & mutate
swrKey(stitch, input) returns the cache key, so you can use SWR's null-key
conditional pattern or target a mutate:
import { swrKey } from '@stitchapi/swr';
import useSWR from 'swr';
// Skip the request until `id` exists.
const { data } = useSWR(id ? swrKey(getUser, { params: { id } }) : null, () =>
getUser({ params: { id } }),
);The key is [name, input], but never your raw input. name is the stitch's
name ?? path ?? url ?? 'stitch' (so two nameless stitches on different paths
can't collide on one entry), and the input is sanitised: the runtime-only signal and
onProgress are dropped — onProgress changes identity every render, which would
refetch forever — and the values of secret-bearing headers are replaced with
[redacted]. The header itself stays, so a call that legitimately varies by
accept-language still gets its own entry.
Secret headers are the fixed denylist (authorization, proxy-authorization,
cookie, set-cookie, x-api-key, x-auth-token), any *-token / *-api-key
spelling, and anything secrets.register has widened —
the same rule @stitchapi/query-core applies to every other binding's query key,
so a credential redacted in a React app is redacted here too. This matters because
SWR keys are persisted by cache providers and shown in devtools: a token in one
outlives the request.
useStitchSWR is for when SWR already owns your view state and you want a
stitch as the fetcher. For StitchAPI to own the lifecycle — and for
streaming — use useStitch / useStitchStream.
The same split applies to TanStack
Query and RTK
Query.
See also
RTK Query
stitchQueryFn turns a stitch into an RTK Query endpoint, and stitchStreamUpdater folds a streaming stitch into the cache — RTK Query keeps the cache, tags, and generated hooks.
TanStack Query
A stitch is the queryFn. StitchAPI owns the call’s resilience; TanStack Query (or SWR) owns view state — they compose, they do not compete.