Files
cabrits-math/components/ui/client-only.tsx
2026-07-05 11:12:45 -04:00

30 lines
840 B
TypeScript

"use client";
import { useSyncExternalStore, type ReactNode } from "react";
const emptySubscribe = () => () => {};
/**
* Renders its children only after hydration on the client. Use this to wrap UI
* whose initial render is non-deterministic (e.g. seeded with Math.random()),
* which would otherwise cause a server/client hydration mismatch. The
* `fallback` is shown during SSR and the first (hydrating) client render.
*
* Uses useSyncExternalStore rather than a mount effect so there is no
* setState-in-effect and the server/client snapshots stay explicit.
*/
export function ClientOnly({
children,
fallback = null,
}: {
children: ReactNode;
fallback?: ReactNode;
}) {
const isServer = useSyncExternalStore(
emptySubscribe,
() => false,
() => true,
);
return <>{isServer ? fallback : children}</>;
}