Skip to content

Live playground ​

All widgets import tanstack-fetch from source and use a mock fetch / stream. Not screenshots.

Open in StackBlitz ​

ExampleStackBlitzDocs
TanStack QueryOpenReact
Next.js SSROpenSSR
UploadOpenUpload
SSEOpenSSE
tRPCOpentRPC recipe
Auth statusOpenRefresh

Status matrix (incl. 429) ​

Live demo · real createFetch

Trigger HTTP statuses

Mock fetch returns the code you click. Handlers fire before FetchError is thrown — including 429 with Retry-After.

Tap a status — real createFetch + mock fetch

Event log

Handlers and throws show up here.

const api = createFetch({
  onTooManyRequests: ({ context }) => {
    const waitMs = parseRetryAfter(context.response?.headers)
    // show toast / backoff…
  },
  onClientError: ({ status }) => console.warn('4xx', status),
  onUnauthorized: () => logout(),
})

React / TanStack Query ​

Live demo · React / TanStack Query

useQuery + useMutation shape

Real createFetch calls — same queryFn / mutationFn contract your React app uses.

idle — click useQuery

const api = createFetch({ baseUrl })

// React Query
useQuery({
  queryKey: ['users'],
  queryFn: ({ signal }) => api.get<User[]>('/users', { signal }),
})

useMutation({
  mutationFn: (body) => api.post<User>('/users', { body }),
})

Next.js SSR ​

Live demo · Next.js SSR

ssr-forward cookie / auth

Real createFetch with source: 'ssr' + ssr-forward — watch headers get attached (then skipped in browser).

Request log

Run server prefetch to see forwarded Cookie / Authorization.

// app/users/page.tsx (Next.js App Router)
import { cookies } from 'next/headers'
import { createFetch } from 'tanstack-fetch'

const createServerApi = async () =>
  createFetch({
    baseUrl: process.env.API_URL!,
    source: 'ssr',
    plugins: ['ssr-forward', 'trace'],
    incoming: async () => ({
      cookie: (await cookies()).toString(),
    }),
  })

await queryClient.prefetchQuery({
  queryKey: ['users'],
  queryFn: async () => (await createServerApi()).get('/users'),
})

Upload ​

Live demo · Upload

api.upload + multipart fields

Real api.upload() builds FormData and posts through createFetch. Add onUploadProgress in your app for XHR progress.

No file selected

0%

Pick a file and upload — real api.upload() + mock fetch

await api.upload('/files', {
  file,
  fieldName: 'file',
  fields: { folder: 'avatars', public: true },
  onUploadProgress: ({ progress }) => setProgress(progress),
})

SSE ​

Live demo · SSE

api.sse over fetch

Real tanstack-fetch/sse against a mock event stream — cookies / Authorization work (unlike EventSource).

Idle — start the stream

import { createFetch } from 'tanstack-fetch/sse'

const api = createFetch({
  plugins: ['sse-resume'],
  getToken: () => localStorage.getItem('access_token'),
})

const stream = api.sse<Tick>('/orders/stream', {
  onMessage: (data) => setTicks((t) => [data, ...t]),
})
// stream.close()

queryFn shape ​

Live demo · queryFn shape

Returns data · throws on error

Click Run — this calls createFetch against a mock API

const api = createFetch({ baseUrl, fetch: mockFetch })

// same shape as TanStack Query queryFn
const users = await api.get<User[]>('/users')

MIT Licensed · Created by Mohammad Garmabi · Not an official TanStack package