Capítulo 18 de 80

Chapter 18: Window Focus Refetching

Core Idea

Returning to a tab with stale data triggers an automatic background refetch via refetchOnWindowFocus; the underlying trigger is pluggable through focusManager, which is exactly what non-browser environments (React Native) need to replace.

Key Concepts

  • Default behavior: refetchOnWindowFocus defaults to true — stale queries refetch automatically when the window regains focus.
  • Scoping the toggle: disable globally via QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false } } }), or per-query via the same option on useQuery.
  • Custom focus source: focusManager.setEventListener(callback) replaces the default visibilitychange-based handler entirely (setting a new one removes the previous), letting you drive focus detection from something other than the DOM.
  • Manual focus override: focusManager.setFocused(true | false) forces a focus state; focusManager.setFocused(undefined) reverts to the default detection mechanism.
  • Non-browser environments: React Native has no window focus events — wire AppState's "change" event to focusManager.setFocused(status === 'active'), guarded by Platform.OS !== 'web' in universal apps.

Code Examples

// Per-query opt-out
useQuery({ queryKey: ['todos'], queryFn: fetchTodos, refetchOnWindowFocus: false })

// Manually driving focus state (e.g. from a non-DOM source)
focusManager.setFocused(true)   // force "focused"
focusManager.setFocused(undefined) // back to default detection
  • What it demonstrates: the per-query escape hatch, and the manual override used when the default visibilitychange detection doesn't apply.

Key Takeaways

  1. refetchOnWindowFocus: true is the default and usually the right choice for a tab-switching web app — disable it deliberately, not reflexively, since it's a cheap way to keep data fresh.
  2. focusManager.setEventListener is the extension point for any non-standard focus source; it fully replaces the previous handler rather than adding to it.
  3. React Native and other non-browser targets need focusManager wired manually — it doesn't work automatically outside the DOM.

Connects To

  • React Native: the concrete AppState wiring for this manager.
  • FocusManager: the full API reference for this class.