useIsDocumentHidden
Track whether the current document is hidden or visible using the Page Visibility API — useful for pausing timers or deprioritizing work when the tab is backgrounded.
useIsDocumentHidden
useIsDocumentHidden returns a boolean that reflects the current tab visibility using the Page Visibility API. It updates when the browser fires the visibilitychange event (e.g., when the user switches tabs, minimizes the window, or brings the tab back to the foreground).
true→ the document is hidden (e.g., in a background tab)false→ the document is visible (active tab)
This hook is ideal for pausing non‑critical work while the tab is hidden (polling, animations, analytics flushes) and resuming when it becomes visible again.
API
function useIsDocumentHidden(): boolean;Prop
Type
Usage
1) Pausing a timer while the tab is hidden
import * as React from 'react';
import { useIsDocumentHidden } from '@loke/ui/use-is-document-hidden';
export function VisibleTimer() {
const hidden = useIsDocumentHidden();
const [count, setCount] = React.useState(0);
React.useEffect(() => {
if (hidden) {
return; // pause while backgrounded
}
const id = setInterval(() => setCount((c) => c + 1), 1000);
return () => clearInterval(id);
}, [hidden]);
return (
<div className="text-sm text-muted-foreground">
{hidden ? '⏸️ Paused (tab hidden)' : `⏱️ Running: ${count}s`}
</div>
);
}2) Deprioritize work when backgrounded
import * as React from 'react';
import { useIsDocumentHidden } from '@loke/ui/use-is-document-hidden';
export function BackgroundAwareFetcher() {
const hidden = useIsDocumentHidden();
React.useEffect(() => {
let abort = new AbortController();
async function fetchData() {
// Skip/short‑circuit when hidden to reduce background noise
if (hidden) return;
await fetch('/api/data', { signal: abort.signal });
// ... update state
}
fetchData();
return () => abort.abort();
}, [hidden]);
return <div>Data loader (skips when tab hidden)</div>;
}How it works
- Reads the current visibility from
document.hidden - Subscribes to
visibilitychangeto update the value whenever the doc visibility changes - Unsubscribes on unmount
// Conceptual outline
const [isHidden, setIsHidden] = useState(document.hidden);
useEffect(() => {
const handle = () => setIsHidden(document.hidden);
document.addEventListener('visibilitychange', handle);
return () => document.removeEventListener('visibilitychange', handle);
}, []);SSR and environments
This hook assumes a browser environment that provides document and the visibilitychange event. Use it inside Client Components (e.g., Next.js "use client") or guard access to document if you must import it on the server.
Common patterns if you need extra safety:
// Option A: Only render this component on the client
'use client';
// Option B: Conditional usage
const isBrowser = typeof document !== 'undefined';
const initial = isBrowser ? document.hidden : false;Tips
- Consider pausing animations or intensive computations when
hiddenistrue. - Combine with throttling/debouncing if you only need occasional refreshes on visibility changes.
- Some browsers may throttle background tabs aggressively; use visibility as a signal to avoid wasted work.
Import
import { useIsDocumentHidden } from '@loke/ui/use-is-document-hidden';useCallbackRef
Return a stable callback that always calls the latest function, avoiding unnecessary re-renders and effect re-runs.
useLayoutEffect
SSR‑safe drop‑in for React’s useLayoutEffect that no‑ops on the server to avoid hydration warnings, while preserving synchronous layout effects on the client.