Queries
Fetch data with type-safe query options
Queries
Any route using GET, HEAD, or OPTIONS is treated as a query procedure. Use queryOptions() to create options for TanStack Query's useQuery.
Basic Query
Using the server from the Getting Started guide:
import { useQuery } from '@tanstack/react-query'
import { useEden } from './lib/eden'
function UserList() {
const eden = useEden()
const { data, isLoading, error } = useQuery(
eden.users.get.queryOptions()
)
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<ul>
{data?.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)
}Query with Input
Pass query parameters as the first argument:
// GET /users?role=admin&status=active
const { data } = useQuery(
eden.users.get.queryOptions({ role: 'admin', status: 'active' })
)Pass additional TanStack Query options as the second argument:
const { data } = useQuery(
eden.users.get.queryOptions(
{ role: 'admin' },
{ staleTime: 5 * 60 * 1000 }
)
)Path Parameters
For routes with dynamic segments, call the path segment as a function. See the Path Parameters guide for details.
// GET /users/:id
const { data } = useQuery(
eden.users({ id: userId }).get.queryOptions()
)useSuspenseQuery
Works with useSuspenseQuery for React Suspense support:
import { useSuspenseQuery } from '@tanstack/react-query'
function UserProfile({ userId }: { userId: string }) {
const eden = useEden()
// data is guaranteed to be defined
const { data } = useSuspenseQuery(
eden.users({ id: userId }).get.queryOptions()
)
return <div>{data.name}</div>
}Query Key
Use queryKey() for cache operations:
const queryClient = useQueryClient()
const eden = useEden()
// Invalidate all users queries
queryClient.invalidateQueries({
queryKey: eden.users.get.queryKey()
})
// Invalidate with specific input
queryClient.invalidateQueries({
queryKey: eden.users.get.queryKey({ role: 'admin' })
})See the Query Keys guide for full details on key structure and cache operations.
Query Filter
Use queryFilter() for invalidation with additional filter options:
queryClient.invalidateQueries(
eden.users.get.queryFilter()
)
// With input filtering
queryClient.invalidateQueries(
eden.users.get.queryFilter({ role: 'admin' })
)
// With additional filter options
queryClient.invalidateQueries(
eden.users.get.queryFilter(undefined, { exact: true, stale: true })
)Conditional Queries with skipToken
Use skipToken to conditionally disable queries:
import { useQuery, skipToken } from '@tanstack/react-query'
function UserProfile({ userId }: { userId: string | null }) {
const eden = useEden()
const { data } = useQuery(
eden.users({ id: userId ?? '' }).get.queryOptions(
userId ? undefined : skipToken
)
)
if (!userId) return <div>Select a user</div>
return <div>{data?.name}</div>
}Abort on Unmount
Enable request cancellation when the component unmounts:
const { data } = useQuery(
eden.users.get.queryOptions(
undefined,
{
eden: {
abortOnUnmount: true
}
}
)
)Prefetching
Prefetch data before it's needed:
const queryClient = useQueryClient()
const eden = useEden()
const handleMouseEnter = () => {
queryClient.prefetchQuery(
eden.users({ id: userId }).get.queryOptions()
)
}Error Handling
Errors are typed as EdenFetchError with access to the HTTP status and response body:
const { data, error } = useQuery(eden.users.get.queryOptions())
if (error) {
if (error.status === 401) {
return <div>Please log in</div>
}
return <div>Error: {error.value?.message}</div>
}