react-hooks
Small, focused, tree-shakeable React hooks — one hook, one subpath, no forced bundle.
react-hooks is a collection of 100+ small, focused React hooks. Each hook ships as its own subpath export — importing one never pulls in unrelated hooks — with SSR-safe defaults and 100% test coverage.
Motivation
Reaching a browser API from React usually means hand-writing a useEffect — a resize listener, a matchMedia subscription, an IntersectionObserver — and each one carries the same two risks: forget the cleanup and you get a leaked listener that keeps firing after unmount, or forget to guard window/document/navigator and the same code throws on the server or hydrates to a value the client’s first render did not have.
react-hooks wraps these APIs — IntersectionObserver, ResizeObserver, the Battery/Geolocation/Share/Wake Lock APIs, matchMedia, and more — behind a small, correct React interface instead of code you write from scratch. Every hook is SSR- and hydration-safe: nothing touches window, document, or navigator outside an effect or a guarded check, so server renders never throw and hydration never mismatches.
Every hook also ships as its own standalone, side-effect-free module — import it on its own and it tree-shakes cleanly. Public hooks never import each other; some share small internal helper modules, so pulling in useIsMobile never drags in unrelated hook code.
Conventions
- Every hook is available both from the top-level
.barrel and from its own subpath (e.g.@zap-studio/react-hooks/sensors/use-is-mobile) — same function either way. - No hook file imports another hook file.
Unstable vs. Experimental
Two different name markers warn about two different kinds of risk:
Unstable— the hook reads a private API with no public type, not guaranteed to stay the same shape between React versions. OnlyuseUnstableFiberanduseUnstableRenderReasoncarry this marker, both in Debug / Observability: they walk react-dom’s internal Fiber tree, the same private structure React DevTools itself reads. The risk is about this package breaking on a React upgrade, not about the browser.Experimental— the hook wraps a browser Web API that MDN itself badges “Experimental,” like the Idle Detection API or Web NFC. The hook’s own code is stable; the risk is that the browser API can change or ship in fewer browsers than you’d like. EveryuseExperimental*hook still fails closed:supported: false(or the equivalent) wherever the underlying API doesn’t exist, instead of throwing.
A hook with neither marker is built entirely on public, standard APIs — safe to treat like any other hook in the package.
Hooks by Category
- Sensors — viewport, network, device, and permission state (
useMediaQuery,useOnlineStatus,useGeolocation,useBattery, …) - DOM / Element Interaction — ref’d-element observers and browser chrome APIs (
useClickOutside,useIntersectionObserver,useFullscreen, …) - Input — keyboard, gamepad, and pointer input (
useKeyPress,useHotkeys,useGamepad, …) - Media — camera, microphone, and screen capture (
useCamera,useMediaRecorder,useSpeechRecognition, …) - History & Navigation —
popstateand the Navigation API (usePopState,useNavigation,useNavigationBlocker, …) - Network — WebSocket and Server-Sent Events (
useWebSocket,useEventSource) - PWA — installability and service worker state (
useInstallPrompt,useServiceWorker, …) - Commerce — the Payment Request API (
usePaymentRequest) - Lifecycle — mount/unmount, timers, and async helpers (
useMount,useInterval,useAsync, …) - State — local, persisted, and cross-tab state (
useLocalStorage,useIndexedDB,useBroadcastChannel, …) - Debug / Observability — render diagnostics (
useRenderCount,useWhyDidYouUpdate,useUnstableFiber, …)
Learn More
- Getting Started — install the package