Server-side rendering
snapgrid works under SSR and static generation. This very site is a statically-exported Next.js app that renders the library. A couple of notes keep it smooth.
Width measurement is SSR-safe
useContainerWidth measures with a ResizeObserver, which only exists in the browser. The hook is
SSR-safe by design:
- it renders at
initialWidth(default1280) on the server and on the first client render, so the markup matches and there’s no hydration mismatch; - it then measures the real width after mount and updates.
const { width, mounted, containerRef } = useContainerWidth({ initialWidth: 1024 });Pick an initialWidth close to your typical container to minimize the first-paint reflow, or gate
on mounted if you’d rather not render until measured.
Avoiding layout flash
Because the server renders at initialWidth, tiles briefly appear at that width before the client
measures. To avoid any flash you can render the grid only once measured:
const { width, mounted, containerRef } = useContainerWidth();
<div ref={containerRef}>
{mounted ? (
<GridLayout layout={layout} width={width} onLayoutChange={setLayout}>
{/* … */}
</GridLayout>
) : (
<div style={{ minHeight: 240 }} />
)}
</div>;Next.js App Router
In the App Router, the file that renders snapgrid (or any of its hooks) must be a client component.
Add "use client" at the top. dnd-kit attaches sensors in effects, so the interaction is inherently
client-side.
"use client";
import { GridLayout, useContainerWidth } from "@snapgridjs/react";
// …The drag overlay portals to document.body, which only exists in the browser. snapgrid guards
this, so it simply renders nothing for the overlay during SSR and mounts it on the client.