useIsomorphicLayoutEffect
useLayoutEffect that quietly becomes useEffect during server rendering.
Usage
import { useIsomorphicLayoutEffect } from '@multinaire/expo-ui';
function MeasuredBox() {
const [width, setWidth] = useState(0);
useIsomorphicLayoutEffect(() => {
setWidth(ref.current.getBoundingClientRect().width);
}, []);
return <View ref={ref} />;
}
The signature is useLayoutEffect's — same effect callback, same dependency array.
Why this exists
React warns when useLayoutEffect is used during SSR, because a layout effect's work can't be encoded into the server-rendered HTML. The usual fix — switching to useEffect — silences the warning but changes behaviour on the client too: a passive effect resolves after the browser paints, so any correction it makes (a measured size, a theme colour) flashes the placeholder value first.
This hook keeps both: useEffect on the server, where the effect never actually runs and the swap is a true no-op, and useLayoutEffect everywhere else, so client-side corrections still land before the first paint.
@multinaire/expo-ui uses it internally in useIsHydrated and useThemeColorSync. It's exported so your own pre-paint effects can be SSR-safe the same way.
Platform Notes
- On native there's no SSR step, so this is always
useLayoutEffect. - The swap is decided once at module load from
Platform.OSandtypeof window, not per render — so the identity of the hook never changes between renders, which is what keeps React's rules-of-hooks happy.