ClientGate
Conditionally render content only after client-side hydration.
The ClientGate component ensures content is rendered only after JavaScript has loaded client-side. This is essential for preventing hydration mismatches and handling browser-only APIs gracefully in SSR environments like Next.js.
Installation
npm install @zayne-labs/ui-reactPreview
Loading...
Basic Usage
Standard usage wraps children that depend on browser APIs.
import { ClientGate } from "@zayne-labs/ui-react/common/client-gate";
function App() {
return (
<ClientGate fallback={<div className="h-64 bg-gray-100 animate-pulse" />}>
<InteractiveMap region="Global" />
</ClientGate>
);
}Use a render callback for deferred initialization of browser-only logic.
import { ClientGate } from "@zayne-labs/ui-react/common/client-gate";
function App() {
return (
<ClientGate fallback={<div>Loading Browser Data...</div>}>
{() => (
<div>
Window width: {window.innerWidth}px
</div>
)}
</ClientGate>
);
}Component Source
"use client";import { useIsHydrated } from "@zayne-labs/toolkit-react";import { isFunction } from "@zayne-labs/toolkit-type-helpers";export type ClientGateProps = { /** * You are encouraged to add a fallback that is the same dimensions * as the client rendered children. This will avoid content layout * shift which is disgusting 🥲 */ children: React.ReactNode | (() => React.ReactNode); fallback?: React.ReactNode;};/** * @description Render the children only after the JS has loaded client-side. Use an optional * fallback component if the JS is not yet loaded. * * @example * **Render a Chart component if JS loads, renders a simple FakeChart * component server-side or if there is no JS. The FakeChart can have only the * UI without the behavior or be a loading spinner or skeleton.** * * ```tsx * return ( * <ClientOnly fallback={<FakeChart />}> * {() => <Chart />} * </ClientOnly> * ); * ``` */function ClientGate(props: ClientGateProps) { const { children, fallback } = props; const isHydrated = useIsHydrated(); const resolvedChildren = () => (isFunction(children) ? children() : children); return isHydrated ? resolvedChildren() : fallback;}export { ClientGate };Component API
Why use ClientGate?
- Zero Hydration Mismatches: Guarantees the server HTML and client initial render are identical (or correctly deferred).
- Safe Browser Access: Safely access
window,localStorage, ordocumentwithin the children. - Improved CLS: By providing a matching fallback, you can maintain Cumulative Layout Shift scores.
// ❌ Dangerous (causes mismatch or crash)
const isDesktop = window.innerWidth > 1024;
// ✅ Safe with ClientGate
<ClientGate fallback={<MobileNav />}>
<DesktopNav />
</ClientGate>;Content inside a ClientGate is invisible to search engines and SEO bots because it only appears
after hydration. Use it sparingly for non-critical UI elements or interactive widgets.
Last updated on