Design Converter
Education
Last updated on Apr 3, 2025
•6 mins read
Last updated on Apr 3, 2025
•6 mins read
React Query simplifies fetching data, caching, and synchronizing server state in React applications. One of its most practical features is the ability to retry failed requests automatically. Mastering React query retry strategies helps developers handle errors gracefully and deliver a better user experience when building resilient applications.
This blog will dig deep into retry logic, explore real-world error-handling patterns, and understand how the retry function works at global and per-query levels. This is based on hands-on experience managing complex API fetch scenarios using React Query (TanStack Query).
APIs can fail due to network instability, 5xx server status, or rate limiting. While some errors should trigger a retry, others, like 400-level client errors, shouldn't. Effective retry logic helps avoid unnecessary loading spinners, ensures users see up-to-date data, and reduces support tickets.
The React query retry mechanism allows granular control over:
• When to retry a failed request
• How many times to retry
• Whether to use a retry function
• What error should stop retrying immediately
By default, React Query retries failed fetches up to three times. You can configure this behavior per query or globally through the QueryClient.
1import { useQuery, QueryClient, QueryClientProvider } from '@tanstack/react-query'; 2 3const queryClient = new QueryClient({ 4 defaultOptions: { 5 queries: { 6 retry: 2, // Retry 2 times by default 7 }, 8 }, 9}); 10 11function App() { 12 return ( 13 <QueryClientProvider client={queryClient}> 14 <MyComponent /> 15 </QueryClientProvider> 16 ); 17}
The above code demonstrates setting a global retry count of 2. Each query will now automatically retry up to two times unless overridden.
The retry function gives you precise control over retry conditions. It allows you to dynamically decide whether to retry based on the error message, status code, or even the number of attempts made.
1const fetchData = async () => { 2 const res = await fetch('/api/data'); 3 if (!res.ok) { 4 const err = new Error('Fetch failed'); 5 err.status = res.status; 6 throw err; 7 } 8 return res.json(); 9}; 10 11const { data, error, isLoading } = useQuery({ 12 queryKey: ['data'], 13 queryFn: fetchData, 14 retry: (failureCount, error) => { 15 if (error.status === 404) return false; // Don't retry on 404 16 if (failureCount >= 3) return false; // Max 3 retries 17 return true; 18 }, 19});
This approach ensures you don’t hammer your API with retries on client errors like 404s, giving you full control over your retry logic.
Use an error logger to log unexpected issues in production. It helps with debugging and supports observability.
1const queryClient = new QueryClient({ 2 defaultOptions: { 3 queries: { 4 retry: (failureCount, error) => { 5 if (failureCount >= 3) { 6 logError(error.message); // Send to monitoring service 7 return false; 8 } 9 return true; 10 }, 11 }, 12 }, 13});
This strategy allows silent retry of transient issues and logs persistent failures after crossing a threshold.
React Query introduces a delay between retries to avoid spamming the server on rapid retries. The retryDelay option can be used to set this delay.
1const queryClient = new QueryClient({ 2 defaultOptions: { 3 queries: { 4 retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000), 5 }, 6 }, 7});
This logic increases the wait time after each failed attempt: 1s, 2s, 4s... up to a cap.
Different error types require different retry handling. Use error, status, message, or a custom string to tailor your response.
Scenario | Should Retry? | Retry Logic |
---|---|---|
Network Timeout | Yes | Retry with exponential backoff |
404 Not Found | No | Return cached data or null fallback |
500 Internal Server Error | Yes | Retry up to 3 times |
401 Unauthorized | No | Redirect to login or refresh token |
You can configure retries globally via the QueryClient , or per individual query. Use global defaults for consistent behavior, and override them in special cases.
Handled in QueryClient initialization as shown earlier.
1useQuery({ 2 queryKey: ['user'], 3 queryFn: fetchUser, 4 retry: (count, error) => { 5 return error.status !== 403 && count < 2; 6 }, 7});
When a query fails permanently, React Query throws the error to be caught by an Error Boundary or displayed via fallback UI. Show helpful messages, not raw error objects.
1if (error) { 2 return <div>Error: {error.message}</div>; 3}
Or configure a fallback component:
1<ErrorBoundary fallback={<ErrorComponent />}> 2 <MyQueryComponent /> 3</ErrorBoundary>
Write integration tests to ensure your retry logic behaves as expected:
1test('retries 3 times before throwing error', async () => { 2 fetchMock.mockRejectOnce(new Error('API Error')); 3 const { findByText } = render(<MyComponent />); 4 expect(await findByText(/error/i)).toBeInTheDocument(); 5});
This validates your error-handling strategy works under real-world conditions.
There are cases where retry is not appropriate:
• Authentication errors
• User cancellations
• Valid empty responses
Returning false in your retry function avoids unnecessary calls.
• Log retry failures using an error logger
• Set smart retry count limits to avoid infinite loops
• Combine retry delay with backoff
• Display clear UI messages to users
• Always catch and handle known errors
• Return null safely when no data is available
Mastering React query retry strategies gives you confidence in building robust React apps with reliable error handling. By understanding how to structure your retry logic, define a retry function, and deal with different error scenarios, you reduce the chance of failed user interactions and broken UI.
A solid grasp of React Query, particularly its retry behavior, means fewer surprises and better control over your data-fetching experience. Keep your requests, responses, and functions tuned for resilience and clarity, and your application will feel faster and more dependable—even in the face of failure.
Ready to level up your error handling with React Query Retry? Make sure your retry strategy is part of your API resilience plan today.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.