This error occurs when React Query hooks are used without wrapping the component tree in a QueryClientProvider. React Query requires a QueryClient instance to be provided via context to manage caching, queries, and mutations.
This error indicates that you're trying to use React Query hooks (like `useQuery`, `useMutation`, or `useQueryClient`) in a component that isn't wrapped by a QueryClientProvider. React Query relies on React's Context API to make the QueryClient instance accessible throughout your component tree. The QueryClient is the core instance that manages all queries, mutations, caching, and data synchronization in React Query. Without the QueryClientProvider wrapper, hooks cannot access this client instance, resulting in the error. This is a common setup issue that typically occurs when first integrating React Query into an application or when creating new components that use React Query hooks without proper provider configuration.
First, import QueryClient and create a new instance. This is typically done at the application root level:
import { QueryClient } from '@tanstack/react-query';
// Create the client instance
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
retry: 1,
},
},
});Note: For React Query v3, import from 'react-query' instead of '@tanstack/react-query'.
Add the QueryClientProvider at the root of your application (typically in App.tsx, index.tsx, or _app.tsx for Next.js):
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Your app components go here */}
<YourComponents />
</QueryClientProvider>
);
}
export default App;For Next.js App Router with Server Components, create a providers component:
// app/providers.tsx
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useState } from 'react';
export function Providers({ children }: { children: React.ReactNode }) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}Then wrap your layout:
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }) {
return (
<html>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}Ensure that any component using React Query hooks is a child of QueryClientProvider:
// ✅ Correct - Component is wrapped by provider
function App() {
return (
<QueryClientProvider client={queryClient}>
<UserProfile /> {/* Can use hooks */}
</QueryClientProvider>
);
}
function UserProfile() {
const { data } = useQuery({
queryKey: ['user'],
queryFn: fetchUser
});
// ...
}
// ❌ Wrong - Hook used outside provider
function App() {
const { data } = useQuery({
queryKey: ['user'],
queryFn: fetchUser
}); // Error!
return (
<QueryClientProvider client={queryClient}>
<div>{data?.name}</div>
</QueryClientProvider>
);
}If you're seeing this error despite having a provider, check for mixed imports between React Query versions:
# Check installed versions
npm list react-query @tanstack/react-queryEnsure you're using consistent imports throughout your codebase:
// ✅ React Query v4+ (current)
import { useQuery } from '@tanstack/react-query';
// ❌ Don't mix with v3 imports
import { useQuery } from 'react-query';If migrating from v3 to v4+, update all imports:
# Remove old version
npm uninstall react-query
# Install new version
npm install @tanstack/react-querySingleton QueryClient Pattern: In most applications, you should create a single QueryClient instance and reuse it throughout your app. Avoid creating multiple instances unless you need isolated caching contexts.
Server-Side Rendering (SSR): When using SSR frameworks like Next.js, create the QueryClient instance inside a component (using useState) rather than at module scope to avoid sharing state between requests:
function Providers({ children }) {
const [queryClient] = useState(() => new QueryClient());
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
}Context Sharing in Micro-Frontends: If you're using multiple React Query instances across different bundles or micro-frontends, you may need to enable context sharing. However, the contextSharing prop is deprecated in v4+. Instead, ensure all parts of your application use the same React Query instance.
Testing: When testing components that use React Query hooks, wrap them in QueryClientProvider with a test client:
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render } from '@testing-library/react';
const createTestQueryClient = () => new QueryClient({
defaultOptions: { queries: { retry: false } },
});
test('my component', () => {
const queryClient = createTestQueryClient();
render(
<QueryClientProvider client={queryClient}>
<MyComponent />
</QueryClientProvider>
);
});Custom Context: For advanced use cases where you need multiple isolated React Query contexts, you can create custom contexts:
import { QueryClient, QueryClientProvider, defaultContext } from '@tanstack/react-query';
const customContext = React.createContext<QueryClient | undefined>(undefined);
<QueryClientProvider client={queryClient} context={customContext}>
{/* Components using this custom context */}
</QueryClientProvider>Prop spreading could cause security issues
Prop spreading could cause security issues
Error: error:0308010C:digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported
React Hook "useEffect" is called conditionally. React Hooks must be called in the exact same order in every component render.
React Hook useEffect placed inside a condition
Hook can only be called inside the body of a function component
Hook can only be called inside the body of a function component
Rollup failed to resolve import during build
How to fix "Rollup failed to resolve import" in React