@usefy/use-page-visibility
v0.25.1
Published
A React hook for tracking document/tab visibility (foreground vs. background) via the Page Visibility API, with an optional onChange callback and SSR support
Maintainers
Readme
Overview
usePageVisibility is part of the @usefy ecosystem — a collection of production-ready, TypeScript-first, SSR-safe React hooks. It reports whether the current tab/window is visible to the user through the Page Visibility API, so you can pause polling, videos, animations, or analytics while the page is in the background.
Features
- Boolean-first —
const visible = usePageVisibility()returns a plainboolean(true= foreground,false= hidden), matching the natural call site - Optional
onChange— passusePageVisibility((visible) => …)to run side effects on each transition; the callback is read through a ref, so replacing it never re-subscribes the listener - SSR-safe & concurrent-safe — built on
useSyncExternalStore; returns a deterministictrueon the server, so there is no hydration mismatch - Leak-free — the
visibilitychangelistener is registered once and cleaned up on unmount - TypeScript-first — full type inference and exported types (
PageVisibilityState,OnVisibilityChange,UsePageVisibilityReturn) - Tiny & tree-shakeable — zero dependencies, published as its own package
Installation
# npm
npm install @usefy/use-page-visibility
# yarn
yarn add @usefy/use-page-visibility
# pnpm
pnpm add @usefy/use-page-visibilityRequires React 18 or 19 (peerDependencies: "react": "^18.0.0 || ^19.0.0").
Quick Start
import { usePageVisibility } from "@usefy/use-page-visibility";
function TabStatus() {
const visible = usePageVisibility();
return <span>{visible ? "👀 Active" : "💤 Background"}</span>;
}Pause work while the tab is hidden:
import { usePageVisibility } from "@usefy/use-page-visibility";
import { useEffect } from "react";
function LiveFeed() {
const visible = usePageVisibility();
useEffect(() => {
if (!visible) return; // don't poll in the background
const id = setInterval(fetchUpdates, 5000);
return () => clearInterval(id);
}, [visible]);
return <Feed />;
}React to transitions with the onChange callback:
import { usePageVisibility } from "@usefy/use-page-visibility";
function Player({ videoRef }: { videoRef: React.RefObject<HTMLVideoElement> }) {
usePageVisibility((visible) => {
if (visible) videoRef.current?.play();
else videoRef.current?.pause();
});
return <video ref={videoRef} />;
}API
usePageVisibility(onChange?): boolean
Returns true while the page is in the foreground and false while it is hidden. The value updates on the document visibilitychange event.
| Parameter | Type | Description |
| ---------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| onChange | (visible: boolean) => void | undefined | Optional. Fired on every visibility transition with the new boolean value. Never fires on mount. Read through a ref (changing it does not re-subscribe). |
Returns: boolean — true when visible, false when hidden. On the server (or any environment without a document) it returns true.
Exported types & helpers
import {
usePageVisibility,
getPageVisibility, // read a one-off boolean snapshot outside React
getVisibilityState, // read the raw "visible" | "hidden" state
isPageVisibilitySupported, // feature detection
SERVER_PAGE_VISIBILITY, // the inert server value (true)
type PageVisibilityState, // "visible" | "hidden"
type OnVisibilityChange, // (visible: boolean) => void
type UsePageVisibilityReturn,
} from "@usefy/use-page-visibility";Browser Support
The Page Visibility API is supported in every modern browser (Chrome, Edge, Firefox, Safari, and their mobile counterparts). In an environment without a document (SSR, tests without a DOM) the hook returns its inert true value and never throws.
Testing
📊 View Detailed Coverage Report (GitHub Pages) — 22 tests, 92% statement coverage.
License
MIT © mirunamu
This package is part of the usefy monorepo.
