Implement visibility-aware polling to reduce background tab resource usage
- Add usePageVisibility hook to track page visibility state - Add pauseWhenHidden option to usePolledData (defaults to false for backward compatibility) - When enabled, polling pauses when page is hidden and resumes with immediate refresh when visible - Refactor useBlocklistStatus to use usePolledData with pauseWhenHidden=true - Add comprehensive tests for usePageVisibility hook - Add polling lifecycle documentation to Web-Development.md Fixes #36: Polling continues when tab is not visible Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1010,6 +1010,45 @@ const load = useCallback(() => {
|
||||
}, []);
|
||||
```
|
||||
|
||||
### Polling Lifecycle & Visibility-Aware Polling
|
||||
|
||||
Regular polling hooks (`usePolledData`, `useBlocklistStatus`, etc.) can consume significant backend resources and client CPU when running in background tabs. To optimize resource usage:
|
||||
|
||||
**`usePolledData` with `pauseWhenHidden`:**
|
||||
|
||||
The `usePolledData` hook accepts a `pauseWhenHidden` option (defaults to `false` for backward compatibility). When enabled:
|
||||
|
||||
- Polling **pauses** when the page becomes hidden (user switched tabs).
|
||||
- Polling **resumes immediately** when the page becomes visible, with a fresh fetch to ensure data is current.
|
||||
- This significantly reduces unnecessary backend load and client resource usage in background tabs.
|
||||
|
||||
```tsx
|
||||
// Poll server status every 30 seconds, pause when tab is hidden
|
||||
const { data: status, loading, error } = usePolledData({
|
||||
fetcher: (signal) => fetchServerStatus(signal),
|
||||
selector: (response) => response.status,
|
||||
errorMessage: "Failed to load server status",
|
||||
pollInterval: 30_000,
|
||||
pauseWhenHidden: true, // Pause in background tabs
|
||||
});
|
||||
```
|
||||
|
||||
**Existing hooks that enable this by default:**
|
||||
|
||||
- `useBlocklistStatus`: Pauses the 60-second blocklist import error polling when hidden.
|
||||
|
||||
**Design considerations:**
|
||||
|
||||
- **Backward compatibility:** `pauseWhenHidden` defaults to `false`. Existing hooks like `useServerStatus` that poll continuously are unaffected.
|
||||
- **On visibility restore:** The hook triggers an immediate refresh to detect any changes that occurred while hidden. This ensures data is current, not stale.
|
||||
- **Edge cases:** Picture-in-Picture windows are treated as hidden (data is paused). If critical alerts require constant monitoring, use `pauseWhenHidden: false`.
|
||||
|
||||
**Internal implementation:**
|
||||
|
||||
The `usePageVisibility` hook tracks the `document.hidden` state via the `visibilitychange` event. This is widely supported (IE 10+) and has no performance overhead — just a single event listener per component tree.
|
||||
|
||||
---
|
||||
|
||||
### Session Validation on App Mount
|
||||
|
||||
The `AuthProvider` uses the `useSessionValidation` hook to validate the cached session with the backend on app mount. This pattern ensures that the UI state always reflects reality — expired or revoked sessions are detected immediately, not after the first API call.
|
||||
|
||||
Reference in New Issue
Block a user