Skip to content

Commit e704a9b

Browse files
committed
docs: add react background retry pausing documentation for v5
1 parent 36ece87 commit e704a9b

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
id: background-retry-pausing
3+
title: Background Retry Pausing
4+
---
5+
6+
When a query fails and retries are enabled, TanStack Query will pause retry attempts when the browser tab loses focus. This behavior ensures that background tabs don't consume unnecessary resources, but it can create unexpected results when combined with `refetchIntervalInBackground`.
7+
8+
## How Retry Pausing Works
9+
10+
By default, **query retries pause when the browser tab is unfocused** and resume when the tab regains focus. This applies to all retry attempts, including:
11+
12+
- Initial query failures
13+
- Refetch interval failures
14+
- Manual refetch failures
15+
16+
[//]: # 'Example'
17+
18+
```tsx
19+
import { useQuery } from '@tanstack/react-query'
20+
21+
// This query will pause retries when tab loses focus
22+
const { data, error } = useQuery({
23+
queryKey: ['posts'],
24+
queryFn: fetchPosts,
25+
retry: 3, // Will pause retries in background
26+
retryDelay: 1000,
27+
})
28+
```
29+
30+
[//]: # 'Example'
31+
32+
When the tab becomes unfocused:
33+
34+
1. Any ongoing retry sequence pauses
35+
2. The query remains in a `pending` state
36+
3. Retries resume when the tab regains focus
37+
38+
## The refetchIntervalInBackground Limitation
39+
40+
The `refetchIntervalInBackground` option controls whether queries should continue refetching when the tab is in the background. However, **this option does not affect retry behavior** - retries still pause regardless of this setting.
41+
42+
[//]: # 'Example2'
43+
44+
```tsx
45+
// Retries still pause when unfocused, even with refetchIntervalInBackground: true
46+
const { data } = useQuery({
47+
queryKey: ['live-data'],
48+
queryFn: fetchLiveData,
49+
refetchInterval: 30000,
50+
refetchIntervalInBackground: true, // Only affects scheduled refetches
51+
retry: 3, // These retries will still pause in background
52+
})
53+
```
54+
55+
[//]: # 'Example2'
56+
57+
## When This Becomes Problematic
58+
59+
This behavior can cause issues in applications that need reliable background operation
60+
61+
[//]: # 'Example3'
62+
63+
```tsx
64+
// Real-world example: polling todo list with retries
65+
const { data } = useQuery({
66+
queryKey: ['todos'],
67+
queryFn: fetchTodos,
68+
refetchInterval: 60000, // Poll every minute
69+
refetchIntervalInBackground: true, // Should work in background
70+
retry: 3, // Retry on failure
71+
})
72+
73+
// Expected: ~12 requests in 3 minutes with network issues
74+
// Actual: Only 2 requests when tab is inactive
75+
```
76+
77+
[//]: # 'Example3'
78+
79+
In the above example, if the network fails while the tab is inactive, retries pause until the user returns to the tab. This defeats the purpose of `refetchIntervalInBackground` for applications that need continuous background synchronization.
80+
81+
## Alternative Approaches
82+
83+
If you need background retries, you can use custom retry logic:
84+
85+
### Custom Retry Function
86+
87+
[//]: # 'Example4'
88+
89+
```tsx
90+
import { focusManager } from '@tanstack/react-query'
91+
92+
const { data } = useQuery({
93+
queryKey: ['critical-data'],
94+
queryFn: fetchData,
95+
refetchInterval: 30000,
96+
refetchIntervalInBackground: true,
97+
retry: (failureCount, error) => {
98+
// Custom logic for background retries
99+
if (!focusManager.isFocused()) {
100+
// Limit background retries to prevent resource abuse
101+
return failureCount < 2 && error.name === 'NetworkError'
102+
}
103+
// Normal retry behavior when focused
104+
return failureCount < 3
105+
},
106+
})
107+
```
108+
109+
[//]: # 'Example4'
110+
111+
### Disabling Background Retries
112+
113+
[//]: # 'Example5'
114+
115+
```tsx
116+
const { data } = useQuery({
117+
queryKey: ['non-critical-data'],
118+
queryFn: fetchData,
119+
refetchInterval: 30000,
120+
refetchIntervalInBackground: true,
121+
retry: (failureCount, error) => {
122+
// Only retry when tab is focused
123+
return focusManager.isFocused() ? failureCount < 3 : false
124+
},
125+
})
126+
```
127+
128+
[//]: # 'Example5'
129+
[//]: # 'Info'
130+
131+
> **Note:** These workarounds have limitations and may not fully solve the underlying architectural constraint. The retry pausing behavior is by design to prevent unnecessary resource consumption in background tabs.
132+
133+
[//]: # 'Info'

0 commit comments

Comments
 (0)