Comparisons
How eden-tanstack-query compares to @ap0nia/eden-react-query and tRPC
Comparisons
Quick Comparison
| Feature | eden-tanstack-query | @ap0nia/eden-react-query | tRPC v11 |
|---|---|---|---|
| Backend | Elysia | Elysia | Any (adapters) |
| API Style | Options-based | Wrapper hooks + cache utilities | Options-based (@trpc/tanstack-react-query) |
| Transport | Plain REST (HTTP methods, URLs) | REST + optional batching | RPC protocol |
| Query Keys | Explicit utilities | tRPC-style utils | Explicit utilities |
| TQ Integration | Native hooks | Wrapper hooks | Native hooks |
| Learning Curve | Standard TanStack Query | tRPC-style API | Standard TanStack Query |
vs @ap0nia/eden-react-query
API Comparison
Basic Query
const eden = useEden()
const { data } = useQuery(eden.users.get.queryOptions())const { data } = eden.users.get.useQuery()Mutations
const createUser = useMutation({
...eden.users.post.mutationOptions(),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: eden.users.get.queryKey() })
}
})const utils = eden.useUtils()
const createUser = eden.users.post.useMutation({
onSuccess: () => utils.users.get.invalidate()
})Key Differences
Options-based vs wrapper hooks — eden-tanstack-query generates options objects that work with any TanStack Query hook (useQuery, useSuspenseQuery, prefetchQuery, fetchQuery). eden-react-query provides tRPC-style wrapper hooks on the route proxy and cache utilities through useUtils().
Explicit query keys — eden-tanstack-query exposes .queryKey(), .queryFilter(), and .infiniteQueryFilter() for full control over cache invalidation. eden-react-query manages keys through tRPC-style utils.
Standard patterns — If you know TanStack Query, you already know eden-tanstack-query. No custom API to learn.
When to Choose
| Choose eden-tanstack-query | Choose @ap0nia/eden-react-query |
|---|---|
| Standard TanStack Query patterns | Prefer tRPC-style wrapper hooks |
| Explicit cache control needed | Utils-based invalidation feels natural |
| Complex invalidation patterns | Coming from tRPC and want that API |
| Already familiar with TanStack Query | Batching support wanted |
Migration from @ap0nia/eden-react-query
1. Update imports
// Before
import { createEdenTreatyReactQuery } from '@ap0nia/eden-react-query'
const eden = createEdenTreatyReactQuery<App>()
// After
import { createEdenTanStackQuery } from 'eden-tanstack-react-query'
import { treaty } from '@elysiajs/eden'2. Setup provider
const { EdenProvider, useEden } = createEdenTanStackQuery<App>()
const edenClient = treaty<App>('http://localhost:3000')
<QueryClientProvider client={queryClient}>
<EdenProvider client={edenClient} queryClient={queryClient}>
<App />
</EdenProvider>
</QueryClientProvider>3. Update queries
// Before: eden.users.get.useQuery()
// After:
const eden = useEden()
const { data } = useQuery(eden.users.get.queryOptions())4. Update mutations
// Before: eden.users.post.useMutation()
// After:
const mutation = useMutation(eden.users.post.mutationOptions())5. Update cache operations
// Before:
const utils = eden.useUtils()
utils.users.get.invalidate()
// After:
queryClient.invalidateQueries(eden.users.get.queryFilter())vs tRPC
Code Comparison
Server
const app = new Elysia()
.get('/users', () => db.users.findMany())
.get('/users/:id', ({ params }) => db.users.findUnique({
where: { id: params.id }
}))
.post('/users', ({ body }) => db.users.create({ data: body }), {
body: t.Object({ name: t.String(), email: t.String({ format: 'email' }) })
})
export type App = typeof appconst appRouter = t.router({
users: t.router({
list: t.procedure.query(() => db.users.findMany()),
get: t.procedure
.input(z.object({ id: z.string() }))
.query(({ input }) => db.users.findUnique({ where: { id: input.id } })),
create: t.procedure
.input(z.object({ name: z.string(), email: z.string().email() }))
.mutation(({ input }) => db.users.create({ data: input }))
})
})
export type AppRouter = typeof appRouterClient
const eden = useEden()
const { data } = useQuery(eden.users.get.queryOptions())
const createUser = useMutation({
...eden.users.post.mutationOptions(),
onSuccess: () => queryClient.invalidateQueries(eden.users.get.queryFilter())
})const trpc = useTRPC()
const queryClient = useQueryClient()
const { data } = useQuery(trpc.users.list.queryOptions())
const createUser = useMutation(trpc.users.create.mutationOptions({
onSuccess: () => queryClient.invalidateQueries(trpc.users.list.queryFilter())
}))Since tRPC v11, @trpc/tanstack-react-query offers the same options-based surface as this library (queryOptions, queryKey, queryFilter, infiniteQueryOptions, mutationOptions, mutationKey). The differences that remain are about the backend and the transport, not the client API style.
Key Differences
| Aspect | eden-tanstack-query | tRPC v11 |
|---|---|---|
| Backend | Elysia (Bun) | Any (Node.js, Bun, etc.) |
| API style | REST (HTTP methods, URL paths) | RPC (procedures in routers) |
| Client surface | Options factories + explicit keys | Options factories + explicit keys |
| Transport | Plain HTTP requests, no codec | tRPC link protocol, optional batching |
| Ecosystem | Elysia plugins | Large tRPC ecosystem |
| Tooling | Standard REST tools (curl, Postman) | Requires tRPC-aware clients |
When to Choose
| Choose eden-tanstack-query | Choose tRPC |
|---|---|
| Using Elysia + Bun | Need backend framework flexibility |
| Prefer REST conventions | Need request batching |
| Types flow from real HTTP routes | Existing tRPC codebase |
| Standard HTTP tooling needed | Need the larger ecosystem |