shadcn.io is an independent project built on shadcn/ui
useIsomorphicLayoutEffect is useLayoutEffect in the browser and useEffect on the server.
Call it the same way you would call useLayoutEffect, with an effect and a dependency list. Use it to measure an element or set scroll position before the browser paints. For a plain client check with no DOM read, use useIsClient. React would warn if you called useLayoutEffect during server render, and this hook avoids that.
Installation
Anatomy

Usage
import {
useIsomorphicLayoutEffect,
} from "@/hooks/use-isomorphic-layout-effect";useIsomorphicLayoutEffect(() => {
const rect = node.getBoundingClientRect();
setWidth(Math.round(rect.width));
}, []);Read the DOM inside the effect, after a ref check. The server uses useEffect, so that read never runs there. The browser uses useLayoutEffect.
FAQ
When should I use this instead of useEffect?
Use it when the browser must apply a DOM change before paint. Measuring an element, writing a scroll position, or adjusting layout that would otherwise flicker belongs here. Data fetching, subscriptions, and logging belong in useEffect, which runs after paint and does not block the frame. If you do not read or write the DOM synchronously, you do not need this hook.
What server warning does this hook avoid?
React warns when useLayoutEffect runs during a server render, because there is no DOM to measure and the effect does nothing useful there. This hook picks useEffect while window is missing, so that path stays quiet. In the browser it picks useLayoutEffect, and the effect still runs before paint. You keep one call site for both environments.
Is the API the same as useLayoutEffect?
Yes. Pass an effect function and an optional dependency list. The effect may return a cleanup, just as it does with useLayoutEffect. Change the import and leave the call alone. There is no extra argument for choosing the environment. The module selects useLayoutEffect or useEffect when it loads, based on whether window is defined.
Is there a performance cost versus useLayoutEffect?
Not in the browser. The exported function is useLayoutEffect itself, not a wrapper that calls it later. On the server the export is useEffect, which does not run during the server render. There is no extra state and no extra render from the hook. The cost you still pay is the usual one: a layout effect blocks paint, so keep the work small.
Does this work when a client component is pre-rendered?
Yes. A client component is still rendered on the server once, and during that render window is undefined, so the hook is useEffect and React does not warn. The browser loads the module again with window defined, so the hook is useLayoutEffect there. Do not read the DOM in the render body. Read it inside the effect, after checking that the ref is set.
How do I measure an element without throwing on the server?
Keep a ref on the element and read getBoundingClientRect inside the effect. On the server the effect does not run, so the DOM call never happens. Guard the ref in case it is missing, and store the size in state from the effect. The first render can show a placeholder size. The layout effect then fills the real numbers before the browser paints.
API Reference
Parameters
effectReact.EffectCallback
Runs after the DOM updates, before the browser paints; may return a cleanup.
deps?React.DependencyList
Re-runs the effect when one of these changes. Every render when left out.











