Installation
Learn how to install and set up TanStack Query in your React application.
Requirements
TanStack Query is compatible with React v18 and v19.
React 18.0.0 or later
React 19.0.0 or later
React Query version 5.90.21 and above supports both React 18 and React 19. Make sure you’re using a compatible version.
Package Installation
Install the package
Install TanStack Query using your preferred package manager: npm install @tanstack/react-query
Install DevTools (Optional)
For development, install the DevTools package: npm install @tanstack/react-query-devtools
The DevTools package is tree-shakeable and only includes development code when NODE_ENV !== 'production', so it’s safe to include in production builds.
Setup
Create a QueryClient
Create a QueryClient instance to manage queries and mutations: import { QueryClient } from '@tanstack/react-query'
const queryClient = new QueryClient ()
You can configure default options for all queries and mutations: const queryClient = new QueryClient ({
defaultOptions: {
queries: {
staleTime: 60 * 1000 , // 1 minute
gcTime: 10 * 60 * 1000 , // 10 minutes
retry: 1 ,
refetchOnWindowFocus: false ,
},
mutations: {
retry: 0 ,
},
},
})
Wrap your app with QueryClientProvider
Provide the QueryClient to your React app using the QueryClientProvider: import { QueryClient , QueryClientProvider } from '@tanstack/react-query'
const queryClient = new QueryClient ()
function App () {
return (
< QueryClientProvider client = { queryClient } >
{ /* Your app components */ }
</ QueryClientProvider >
)
}
export default App
Add DevTools (Development)
Import and add the DevTools component for development: import { QueryClient , QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
const queryClient = new QueryClient ()
function App () {
return (
< QueryClientProvider client = { queryClient } >
{ /* Your app components */ }
< ReactQueryDevtools initialIsOpen = { false } />
</ QueryClientProvider >
)
}
export default App
The DevTools component only renders in development mode (NODE_ENV === 'development'), so you don’t need to conditionally import it.
Complete Example
Here’s a complete setup example:
import React from 'react'
import ReactDOM from 'react-dom/client'
import { QueryClient , QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import App from './App'
// Create a client
const queryClient = new QueryClient ({
defaultOptions: {
queries: {
staleTime: 60 * 1000 ,
retry: 1 ,
},
},
})
ReactDOM . createRoot ( document . getElementById ( 'root' ) ! ). render (
< React.StrictMode >
< QueryClientProvider client = { queryClient } >
< App />
< ReactQueryDevtools initialIsOpen = { false } />
</ QueryClientProvider >
</ React.StrictMode > ,
)
Configuration Options
Customize the QueryClient with these common options:
Query Options
Option Type Default Description staleTimenumber | Infinity0Time in ms until data becomes stale gcTimenumber | Infinity5 * 60 * 1000Time in ms unused data stays in cache retryboolean | number | function3Number of retry attempts for failed queries retryDelaynumber | functionexponential backoff Delay between retries refetchOnWindowFocusboolean | "always"trueRefetch on window focus refetchOnMountboolean | "always"trueRefetch on component mount refetchOnReconnectboolean | "always"trueRefetch when reconnecting refetchIntervalnumber | falsefalseInterval for automatic refetching
Mutation Options
Option Type Default Description retryboolean | number | function0Number of retry attempts for failed mutations retryDelaynumber | functionexponential backoff Delay between retries
Be careful with aggressive retry settings in production, as they can impact server load and user experience.
Environment-Specific Configuration
Configure different settings for development and production:
const queryClient = new QueryClient ({
defaultOptions: {
queries: {
staleTime: process . env . NODE_ENV === 'production' ? 60 * 1000 : 0 ,
gcTime: process . env . NODE_ENV === 'production' ? 10 * 60 * 1000 : 5 * 60 * 1000 ,
retry: process . env . NODE_ENV === 'production' ? 3 : 1 ,
refetchOnWindowFocus: process . env . NODE_ENV === 'production' ,
},
},
})
Next.js Setup
For Next.js applications, create a separate client component:
'use client'
import { QueryClient , QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { useState } from 'react'
export function Providers ({ children } : { children : React . ReactNode }) {
const [ queryClient ] = useState (
() =>
new QueryClient ({
defaultOptions: {
queries: {
staleTime: 60 * 1000 ,
},
},
}),
)
return (
< QueryClientProvider client = { queryClient } >
{ children }
< ReactQueryDevtools initialIsOpen = { false } />
</ QueryClientProvider >
)
}
Then use it in your root layout:
import { Providers } from './providers'
export default function RootLayout ({
children ,
} : {
children : React . ReactNode
}) {
return (
< html lang = "en" >
< body >
< Providers > { children } </ Providers >
</ body >
</ html >
)
}
Always create the QueryClient inside a component using useState to ensure each request gets a new client instance in Server Components.
Persister Setup (Optional)
To persist query cache across sessions:
npm install @tanstack/react-query-persist-client
import { QueryClient } from '@tanstack/react-query'
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persister'
const queryClient = new QueryClient ({
defaultOptions: {
queries: {
gcTime: 1000 * 60 * 60 * 24 , // 24 hours
},
},
})
const persister = createSyncStoragePersister ({
storage: window . localStorage ,
})
function App () {
return (
< PersistQueryClientProvider
client = { queryClient }
persistOptions = { { persister } }
>
{ /* Your app */ }
</ PersistQueryClientProvider >
)
}
Verification
Verify your installation by creating a simple query:
import { useQuery } from '@tanstack/react-query'
function App () {
const { data , isLoading } = useQuery ({
queryKey: [ 'hello' ],
queryFn : async () => {
const response = await fetch ( 'https://api.example.com/hello' )
return response . json ()
},
})
if ( isLoading ) return < div > Loading... </ div >
return < div > Data: { JSON . stringify ( data ) } </ div >
}
export default App
If you see the DevTools floating button in the bottom-right corner of your app, React Query is successfully installed!
Next Steps
Quick Start Build your first React Query application
TypeScript Configure TypeScript for type-safe queries