SSR and RSC
The server can render useful markup, but it cannot know a visitor's viewport, clipboard, connection, or storage. Better Hooks keeps that gap visible instead of guessing.
Put the boundary beside the Hook
A Better Hook must run in a Client Component. Put 'use client' in the smallest component that calls it. A Server Component can render that child and pass serializable props, but it cannot call the Hook itself.
Importing is safe; calling is client work
Importing the package does not register listeners, start timers, read storage, or touch the DOM. That makes an import safe in a server build. Calling the Hook still belongs in the client tree.
Start with a steady fallback
Browser-facing Hooks return a documented server value:
| Hook | Server result |
|---|---|
useMediaQuery | defaultMatches, otherwise false |
useWindowSize | { width: 0, height: 0 } |
useOnline | true |
| storage Hooks | the initial value you provide |
| listener and timer Hooks | no subscription or timer during server rendering |
Choose an explicit initial value when the neutral default is not right for your UI.
Let hydration fill in the browser value
Render a useful first frame, then let React reconcile the live browser snapshot after hydration. Avoid replacing a large part of the page only because a measurement was unknown on the server.
Treat missing browser APIs as normal
A browser API may be unavailable or may reject access. Each Hook either returns its documented fallback or exposes the error. Keep a neutral UI available instead of assuming the capability is always present.