Why is TanStack Creating a Library for Everything - Query, Router, Table, Form, Hotkeys?
Purpose
When I saw TanStack release yet another library—Hotkeys—I wondered why Tanner Linsley keeps building new tools instead of improving existing ones. Query, Router, Table, Form, Hotkeys, Virtual, Store… when does it stop?
This post explains what makes TanStack’s philosophy different from the fragmented React ecosystem.
What I Found
I noticed a Reddit thread about TanStack Hotkeys alpha release. The top comment joked about “Tanner Linsley collecting infinity stones to snap away inferior frameworks.” But another comment asked the real question: “Are they just going to make a TanStack version of every package?”
I had the same question. We already have React Router, React Query, AG Grid, Formik. Why rebuild everything?
The Fragmented Problem
When I build React apps, I mix libraries from different authors:
- State management: Redux, Zustand, or Jotai
- Data fetching: SWR, React Query, or Apollo
- Routing: React Router v6 or Next.js App Router
- Tables: Material-UI, AG Grid, or React Table
- Forms: Formik, React Hook Form, or Final Form
Each library has different patterns. Redux uses selectors. React Hook Form uses watch(). React Router uses useSearchParams(). The TypeScript support varies. The learning curves pile up.
I tried mixing SWR for data fetching with React Router for navigation:
// SWR gives you `any` typesconst { data, error } = useSWR('/api/users', fetcher)// data is any, error is any
// React Router v6 gives loose string typesconst params = useParams()// params is Record<string, string | undefined>
// Formik requires boilerplate<Formik initialValues={{ email: '' }} validationSchema={Yup.object().shape({ email: Yup.string().email().required() })}> {({ values, handleChange }) => ( <input name="email" value={values.email} onChange={handleChange} /> )}</Formik>The patterns don’t align. I copy-paste type definitions. I write wrapper functions to bridge APIs. The cognitive overhead adds up.
What Makes TanStack Different
I looked into TanStack’s libraries and found they share core principles.
Headless by Default
TanStack Table doesn’t render tables. It gives you sorted, filtered data. You render the HTML. TanStack Form doesn’t render inputs. It manages validation state. You render the UI.
This means full control over styling and markup. No forced component trees. No design system lock-in.
Framework Agnostic
TanStack Query works in React, Vue, Svelte, and Solid. The core logic is framework-independent. Adapters handle framework-specific integration.
I can write the same Query code in React and Vue:
// Same API in Reactconst { data } = useQuery({ queryKey: ['users'], queryFn: fetchUsers})
// Same API in Vueconst { data } = useQuery({ queryKey: ['users'], queryFn: fetchUsers})Type Safety First
Most React libraries added TypeScript as an afterthought. TanStack designed with TypeScript from day one.
TanStack Router infers route param types from path definitions:
// Define route: /users/:userIdconst route = createFileRoute('/users/$userId')({ loader: ({ params }) => { // params.userId is automatically typed as `string` return fetchUser(params.userId) }})
// In componentconst params = useParams()// params.userId is `string`, not `string | undefined`TanStack Query infers return types from query functions:
const { data } = useQuery({ queryKey: ['users'], queryFn: () => fetch('/api/users').then(r => r.json())})// data is automatically inferred as User[]Composability
The libraries work independently or together. Use Query for server state. Add Router for navigation. Use Table for data grids. The patterns stay consistent.
TanStack Router integrates with TanStack Query:
const route = createFileRoute('/users/$userId')({ loader: ({ params, context }) => { // params.userId is typed from route definition return context.queryClient.ensureQueryData({ queryKey: ['users', params.userId], queryFn: () => fetchUser(params.userId) }) }})The route param types flow into the query cache key types. End-to-end type safety from URL to database.
Why Build Everything?
I considered the alternatives. Why not use React Router? It’s mature. Why not use AG Grid? It’s feature-rich.
But I found issues:
Inconsistent Patterns
React Router, React Hook Form, and Redux have different APIs. Different mental models. Different error handling. TanStack provides one consistent approach.
Weak TypeScript Support
Many libraries use any types or require manual generics. TanStack infers types automatically. Less typing, fewer errors.
Framework Lock-in
React Router only works in React. AG Grid only works in React. If I switch to Vue or Svelte, I relearn everything. TanStack’s framework-agnostic core means my skills transfer.
Missing Features
TanStack Query popularized stale-while-revalidate caching. TanStack Router introduced type-safe routing with param inference. TanStack Table pioneered headless data grids. Innovation required building from scratch.
The TanStack Ecosystem
Here’s what TanStack offers:
| Library | Purpose | Key Innovation |
|---|---|---|
| Query | Server state | Stale-while-revalidate, background refetching |
| Router | Type-safe routing | Route param inference, search params validation |
| Table | Headless data grids | Virtualization, sorting, filtering without UI |
| Form | Form validation | Type-safe field access, minimal re-renders |
| Hotkeys | Keyboard shortcuts | Composable combinations, conflict resolution |
| Virtual | List virtualization | Frame-perfect scrolling, dynamic sizing |
| Store | Client state | Simple, type-safe, framework-agnostic |
Benefits I Found
Developer Experience
One documentation site. Consistent API patterns. Single TypeScript configuration. Unified error handling.
Type Safety Across Boundaries
Router types flow into Query cache keys. Form validation types integrate with Table filters. Hotkey triggers typed with Router actions.
Performance
Libraries designed to work together. Avoid duplicate state management. Shared utilities reduce bundle size. Coordinated re-render optimization.
Future-Proofing
Framework-agnostic core survives framework shifts. Migrate from React to Vue without relearning patterns. Adopt libraries incrementally.
When I Use TanStack
I reach for TanStack when I want:
- Full TypeScript inference without manual generics
- Headless libraries that don’t dictate UI
- Framework-agnostic code that survives framework shifts
- Consistent patterns across all concerns
I don’t use TanStack when:
- I need a quick prototype with existing tools
- My team already knows a different stack well
- I only need one specific feature (not the ecosystem)
Summary
In this post, I explained why TanStack builds libraries for everything. The key point is that TanStack’s libraries share a unified philosophy—headless, framework-agnostic, and fully type-safe—while the React ecosystem remains fragmented with inconsistent patterns.
TanStack isn’t reinventing wheels. It’s building a complete toolkit with consistent developer experience, end-to-end type safety, and framework flexibility.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 TanStack Query Documentation
- 👨💻 TanStack Router Documentation
- 👨💻 TanStack Table Documentation
- 👨💻 TanStack Form Documentation
- 👨💻 Reddit discussion about TanStack ecosystem expansion
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments