Skip to main content

useIsomorphicLayoutEffect

useIsomorphicLayoutEffect is a hook that runs browser layout work before paint, such as measuring an element or positioning a tooltip.

Import

import { useIsomorphicLayoutEffect } from '@vortexlabs/vortex';
Measured width: Pending
"use client";

import { Button, Stack, Text, useIsomorphicLayoutEffect } from "@vortexlabs/vortex";
import React from "react";

export const LayoutMeasurementExample = () => {
  const ref = React.useRef<HTMLDivElement>(null);
  const [compact, setCompact] = React.useState(false);
  const [width, setWidth] = React.useState<number | null>(null);
  useIsomorphicLayoutEffect(() => {
    setWidth(ref.current?.getBoundingClientRect().width ?? null);
  }, [compact]);
  return (
    <Stack gap={4} width="100%">
      <Button variant="secondary" onClick={() => setCompact((value) => !value)}>
        Toggle width
      </Button>
      <div ref={ref} style={{ width: compact ? "50%" : "100%" }}>
        <Stack padding={4} backgroundColor="surface-subtlest">
          <Text size="body-sm-desktop">
            Measured width: {width === null ? "Pending" : Math.round(width) + "px"}
          </Text>
        </Stack>
      </div>
    </Stack>
  );
};

Features

  • Uses React’s layout effect in the browser.
  • Selects React’s regular effect on the server.
  • Accepts effect dependencies and cleanup.

Pass an effect callback and optional dependencies. The hook returns nothing; omit dependencies to run after every committed render.

Observing Later Resizes

Use ResizeObserver for size changes outside React. Return cleanup to disconnect the observer.

"use client";

import React from "react";
import { useIsomorphicLayoutEffect } from "@vortexlabs/vortex";

export const ObservedWidth = () => {
  const ref = React.useRef<HTMLDivElement>(null);
  const [width, setWidth] = React.useState<number | null>(null);
  useIsomorphicLayoutEffect(() => {
    const element = ref.current;
    if (!element) return;
    const measure = () => setWidth(element.getBoundingClientRect().width);
    measure();
    const observer = new ResizeObserver(measure);
    observer.observe(element);
    return () => observer.disconnect();
  }, []);
  return (
    <div ref={ref}>Width: {width === null ? "Pending" : Math.round(width) + "px"}</div>
  );
};

Effects do not run during server rendering. Keep the initial UI valid before measurement, and use React’s useEffect for work that does not need to run before paint.