LOKE Design System
Hooks

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 visibilitychange to 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 hidden is true.
  • 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';