A few months ago, I introduced tanstack-fetch, a typed HTTP client designed around the mental model of TanStack Query.
Since then, I've been using the feedback from the first release to improve the API, fix issues, and make the developer experience smoother.
Today, tanstack-fetch 1.2.1 is available.
This release is not about adding dozens of new features.
It's about making the existing ones more reliable and easier to use.
What's tanstack-fetch?
If you're using TanStack Query, you probably already have code like this:
useQuery({
queryKey: ['users'],
queryFn: async ({ signal }) => {
const response = await fetch('/api/users', { signal })
if (!response.ok) {
throw new Error('Request failed')
}
return response.json()
},
})
The idea behind tanstack-fetch is to move the HTTP concerns into a reusable, typed client:
const api = createFetchClient({
baseURL: '/api',
})
useQuery({
queryKey: ['users'],
queryFn: ({ signal }) =>
api.get<User[]>('/users', { signal }),
})
The goal is simple:
Let TanStack Query handle server state, while tanstack-fetch handles HTTP.
What's improved in 1.2.1?
The main focus of this release was developer experience and reliability.
Better TypeScript experience
One of the most important goals of the project is to keep the API strongly typed without forcing developers to write a lot of boilerplate.
const user = await api.get<User>('/users/123')
The response type flows directly into your TanStack Query code:
const { data } = useQuery({
queryKey: ['user', userId],
queryFn: ({ signal }) =>
api.get<User>(`/users/${userId}`, { signal }),
})
The result stays fully typed.
Better error handling
HTTP errors should be useful.
Instead of checking response.ok and manually parsing the response every time, tanstack-fetch provides a structured FetchError.
try {
await api.get<User>('/users/123')
} catch (error) {
if (error instanceof FetchError) {
console.log(error.status)
console.log(error.message)
console.log(error.data)
}
}
This also makes it easier to integrate HTTP errors with TanStack Query's error handling.
useQuery({
queryKey: ['user'],
queryFn: ({ signal }) =>
api.get<User>('/users/123', { signal }),
retry: (failureCount, error) => {
if (error instanceof FetchError && error.status === 404) {
return false
}
return failureCount < 3
},
})
AbortSignal support
Cancellation is especially important when using TanStack Query.
TanStack Query already provides an AbortSignal to the query function:
useQuery({
queryKey: ['users'],
queryFn: ({ signal }) =>
api.get<User[]>('/users', {
signal,
}),
})
tanstack-fetch passes that signal through to the underlying Fetch API.
This means requests can be cancelled naturally when queries become obsolete.
Designed for modern TypeScript applications
The project is designed around modern web applications rather than trying to replace every HTTP client.
Current use cases include:
- TanStack Query
- React
- TypeScript
- Vite
- Next.js
- SSR
- SSE
- file uploads
- authentication
- request interceptors
- retries
- OpenAPI-generated clients
The core idea remains the same:
TanStack Query
↓
tanstack-fetch
↓
Fetch API
↓
Your backend
Why not just use Axios?
You absolutely can.
Axios is a mature and widely used HTTP client.
The reason I built tanstack-fetch is different.
Modern applications already have a Fetch API, and TanStack Query already provides the server-state abstraction.
I wanted a small layer between them that focuses on:
- TypeScript
- Fetch
- TanStack Query
- consistent errors
- cancellation
- authentication
- SSR
- developer experience
Instead of introducing a large abstraction, the goal is to stay close to the platform.
What's next?
Version 1.2.1 is another step toward making the package more stable and useful for real-world applications.
Some of the areas I'm currently interested in improving are:
- better documentation
- more real-world examples
- Next.js App Router examples
- TanStack Start examples
- better OpenAPI workflows
- performance benchmarks
- more tests
- better developer tooling
I'm also interested in hearing from developers who are actually using it.
If you try tanstack-fetch in a project, I'd love to hear what works well and what doesn't.
Install
npm install tanstack-fetch
or:
pnpm add tanstack-fetch
GitHub:
https://github.com/mohamadgarmabi/tanstack-fetch
NPM:
https://www.npmjs.com/package/tanstack-fetch
Final thoughts
Building a developer tool is a little different from building an application.
The API can look good on day one, but the real test is what happens after people start using it.
That's what I'm focusing on with tanstack-fetch now:
less friction, better types, better DX, and a reliable HTTP layer for TanStack Query.
If you're using TanStack Query and Fetch, give tanstack-fetch a try.
And if you find a bug or have an idea, feel free to open an issue or contribute on GitHub.
Thanks for reading.
Top comments (0)