Skip to Content
🎉 Try out our new interactive playground
GuidesUse with react-query

Using with tanstack react-query

Tanstack Query  is a popular data fetching library for react applications. We don’t offer any out the box integration with it (yet), but it does integrate easily with our generated client SDKs.

Here’s a basic example implementation. It’s not perfect, but it should give you a good starting point.

Define the queries and mutations

First we setup a context and define the queries / mutations we’ll be making

import {ApiClient} from "@/generated/clients/client" import {t_ScanRepositoriesBodySchema} from "@/generated/models" import { QueryClient, UseMutationOptions, queryOptions, } from "@tanstack/react-query" import {createContext, useContext} from "react" export const QueryOptionsContext = createContext< ReturnType<typeof createQueryOptions> | null >(null) export const useQueryOptions = () => { const v = useContext(QueryOptionsContext) if (!v) throw new Error("useQueryOptions must be used within provider") return v } export const createQueryOptions = ( fetchClient: ApiClient, queryClient: QueryClient, ) => { const result = { getSomeResource: ( id: string, ) => { return queryOptions({ queryKey: [ "getSomeResource", id ], queryFn: async () => { const res = await fetchClient.getSomeResource({ id, }) if (res.status !== 200) { throw new Error("request failed", { cause: new Error(await res.text()), }) } return await res.json() }, }) }, updateSomeResource: (): UseMutationOptions< void, Error, t_ScanRepositoriesBodySchema > => { return { mutationKey: ["updateSomeResource"], mutationFn: async (id: string, body: t_SomeBodyType) => { const res = await fetchClient.updateSomeResource({id, requestBody: body}) if (res.status !== 204) { throw new Error("request failed", { cause: new Error(await res.text()), }) } }, onSuccess: () => { void queryClient.invalidateQueries({queryKey: ["updateSomeResource"]}) }, } }, } return result }

Initialize the clients

At the root of our application provide the context

import { QueryOptionsContext, createQueryOptions, } from "@/app/providers/query-options" import {ApiClient} from "@/generated/clients/client" import {QueryClient, QueryClientProvider} from "@tanstack/react-query" import {ReactQueryDevtools} from "@tanstack/react-query-devtools" import {ReactQueryStreamedHydration} from "@tanstack/react-query-next-experimental" import * as React from "react" import {useState} from "react" export function ClientProviders(props: {children: React.ReactNode}) { const [queryClient] = useState( () => new QueryClient({ defaultOptions: { queries: { staleTime: 5_000, }, }, }), ) const [fetchClient] = useState( new ApiClient({ basePath: "http://localhost:3000", }), ) return ( <QueryClientProvider client={queryClient}> <QueryOptionsContext.Provider value={createQueryOptions(fetchClient, queryClient)} > <ReactQueryStreamedHydration> {props.children} </ReactQueryStreamedHydration> <ReactQueryDevtools initialIsOpen={false} /> </QueryOptionsContext.Provider> </QueryClientProvider> ) } export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( <html lang="en"> <head> <meta name="viewport" content="initial-scale=1, width=device-width" /> </head> <body> <ClientProviders> {children} </ClientProviders> </body> </html> ) }

Use the queries

Finally use the useQueryOptions hook in conjunction with the normal useQuery / useMutation hooks to make your requests

import {useQueryOptions} from "@/app/providers/query-options" import {useMutation, useQuery} from "@tanstack/react-query" export const SomeComponent = () => { const queryOptions = useQueryOptions() const someResource = useQuery( queryOptions.getSomeResource("123"), ) const doUpdate = useMutation(queryOptions.updateSomeResource()) return <div> <h1>{someResource.title}</h1> <button onClick={() => doUpdate.mutate("123", {title: "new title"})}/> </div> }
Last updated on