Measure and position visual elements
A tooltip or popover needs its DOM dimensions to calculate a position before becoming visible.
React 19+ · Hook
useLayoutEffect runs before the browser repaints, making it suitable for layout reads and visual corrections that must not flicker. Prefer useEffect unless the work must happen before paint.
useLayoutEffect runs after React commits DOM changes but before the browser repaints. Use it when a visual effect must synchronously read layout and possibly update state before the user sees the result; otherwise prefer useEffect.
useLayoutEffect(setup, dependencies?)| Name | Type | Description |
|---|---|---|
setup | () => void | (() => void) | Function containing the effect logic; it may optionally return a cleanup function. |
dependencies | DependencyList | Optional inline list of reactive values referenced by setup. |
undefined
import { useLayoutEffect, useRef, useState } from "react";
export default function Tooltip() {
const ref = useRef<HTMLDivElement>(null);
const [height, setHeight] = useState(0);
useLayoutEffect(() => {
setHeight(ref.current?.getBoundingClientRect().height ?? 0);
}, []);
return <div ref={ref} style={{ top: -height }}>Tooltip</div>;
}Measures the tooltip before the browser paints, allowing its position to use the measured height without a visible intermediate layout.
A tooltip or popover needs its DOM dimensions to calculate a position before becoming visible.
A component must read an element's bounding box immediately after commit and use it to render a corrected layout.
An external visual system requires setup and teardown that must occur before repaint.
useLayoutEffect is the layout-sensitive counterpart to useEffect. It runs before the browser repaints, so it can measure DOM layout and update state before the user sees the result.
Follow-up: When should useEffect be preferred? Prefer it for ordinary side effects, because useLayoutEffect blocks painting and can make the app slower.
The setup function contains the effect logic and may return cleanup logic. The optional dependency list contains reactive values referenced by setup; React reruns the effect when those dependencies change.
Follow-up: What should the dependency list look like? It should have a constant number of items and be written inline, such as [dep1, dep2].
Effects run only on the client, not during server rendering. Therefore, layout measurements must happen after the component is available in the browser.
Follow-up: What alternative avoids blocking the initial paint? Replace useLayoutEffect with useEffect when an initial visual adjustment does not need to happen before paint.
useEffectuseRefuseState