This error occurs when trying to access the queryCache property before the QueryClient is properly initialized or when the QueryClientProvider is not correctly set up in your component tree.
This error indicates that the `queryCache` property is being accessed on an undefined or uninitialized QueryClient instance. In TanStack Query (formerly React Query), the queryCache is a core component that stores and manages all cached query data. When you see "undefined is not an object (evaluating queryCache)", it means the code is trying to access `queryClient.queryCache` or similar properties before the QueryClient has been properly created or provided to your component tree. This typically happens in one of three scenarios: the QueryClient was never instantiated, the QueryClientProvider wasn't set up correctly to wrap your components, or the QueryClient instance was recreated (causing cache loss) instead of being kept stable across re-renders. The error is particularly common when migrating from older versions of React Query or when setting up React Query for the first time in a new project.
Ensure your QueryClient is created outside of any component to keep it stable across renders:
// app.tsx or _app.tsx
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
// Create the client outside the component
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000, // 1 minute
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
<YourComponents />
</QueryClientProvider>
);
}Creating the QueryClient at module level ensures it persists across re-renders and maintains the cache.
Make sure QueryClientProvider is placed high enough in your component tree to wrap all components that use React Query hooks:
// Correct setup
function Root() {
const queryClient = new QueryClient();
return (
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
}
// In App or child components
function MyComponent() {
const { data } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos
});
// This will now work because QueryClientProvider is above
}Every component using useQuery, useMutation, or other React Query hooks must be a descendant of QueryClientProvider.
Verify you have the correct version of TanStack Query installed:
# For React Query v5 (TanStack Query)
npm install @tanstack/react-query
# Check your package.json
npm list @tanstack/react-queryIf you're using an older version, update your imports:
// Modern import (v4+)
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
// Old import (v3 and earlier) - deprecated
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';Ensure all React Query imports come from the same package version throughout your project.
If you must create the QueryClient inside a component (e.g., in Next.js App Router), memoize it:
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useState } from 'react';
function Providers({ children }: { children: React.ReactNode }) {
// Create a stable QueryClient instance
const [queryClient] = useState(() => new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
},
},
}));
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}Using useState with a lazy initializer ensures the QueryClient is only created once, not on every render.
If you're directly accessing queryCache, ensure you're doing so correctly:
import { useQueryClient } from '@tanstack/react-query';
function MyComponent() {
const queryClient = useQueryClient();
// Correct way to access queryCache
const handleClearCache = () => {
queryClient.getQueryCache().clear();
};
// Or access specific queries
const cachedQuery = queryClient.getQueryCache().find({
queryKey: ['todos']
});
return <button onClick={handleClearCache}>Clear Cache</button>;
}Always use useQueryClient() hook to get the client instance within components, and use getQueryCache() method to access the cache.
Version-specific considerations:
In React Query v3 and earlier, the QueryCache was more directly accessible. Starting with v4 (TanStack Query), the architecture changed to make QueryCache more of an internal implementation detail. If you're migrating from v3, you may need to update code that directly accessed queryClient.queryCache to use queryClient.getQueryCache() instead.
SSR and hydration:
In Next.js or other SSR frameworks, be careful about QueryClient initialization. For Next.js App Router, create a separate client component for the QueryClientProvider to ensure proper hydration. For Pages Router, initialize the QueryClient in _app.tsx at the module level.
QueryCache event listeners:
If you're setting up global error handling or cache event listeners, ensure they're configured when creating the QueryClient:
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: (error, query) => {
console.error('Query error:', error, query.queryKey);
},
}),
});DevTools consideration:
If you're using React Query DevTools and experiencing this error, ensure DevTools are imported after QueryClientProvider is set up and only in development builds.
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