Hirefullstack – Software Engineering & IT-Beratung aus Berlin
← Back to overview
Advanced 8 min read

useLayoutEffect & useInsertionEffect

Measure and correct before the browser paints

Builds on: useEffect
In one sentence

Almost the same as useEffect – but it runs before the browser shows the picture. That is how you stop visible flicker.

You will rarely need this hook. It exists for exactly one case: you have to measure something and immediately change a position because of it – and the user should not see the in-between step.

timing.txt
Draw  →  page updated  →  useLayoutEffect  →  browser paints  →  useEffect
                            ▲ the browser waits here     ▲ not any more

You write both hooks in exactly the same way. The only difference is the moment – and that decides whether an in-between state flashes up.

Put another way

useEffect is “the picture is in the frame, now let me straighten it” – you see it hang crooked for a moment. useLayoutEffect straightens the frame before the curtain goes up.

The typical case: measure and position

tooltip.tsx
function Tooltip({ target, children }) {
  const ref = useRef<HTMLDivElement>(null);
  const [top, setTop] = useState(0);

  useLayoutEffect(() => {
    const height = ref.current!.getBoundingClientRect().height;
    const space = target.getBoundingClientRect().top;
    setTop(space < height ? space + 20 : space - height);   // below instead of above
  }, [target]);

  return <div ref={ref} style={{ top }}>{children}</div>;
}
With useEffect the tooltip would first appear in the wrong place and then jump.
Reach for it when …
  • +

    Measuring the page and immediately correcting position or size (tooltips, popovers, dropdowns)

  • +

    Setting the scroll position before the user sees the jump

  • +

    Flicker you have actually observed in the browser

Skip it when …
  • Everything else – useEffect is the default

  • Loading data, subscriptions, timers

  • Server rendering: it does not run there and warns in the console

Careful The browser waits meanwhile

Everything inside useLayoutEffect runs before the user sees anything. A lot of work there makes the page noticeably hang. Only use it to fix flicker you have really seen.

In more depth: server rendering and useInsertionEffect optional

With Server rendering (SSR)The page is produced as finished HTML on the server, so the browser can show something straight away. there is no page to measure – the hook simply does not run there, and React warns in the console. The usual fixes: only draw the component in the browser, or fall back to useEffect.

Good to know useInsertionEffect exists too

It runs even earlier – before React changes the page at all. It exists essentially so styling libraries can insert their <style> blocks without distorting measurements. You will never need it in your own code.

Does it stick?

3 questions on this lesson. Wrong answers show up in your stats.

Hirefullstack

Need React firepower on your team?

We have been building React and Next.js applications for clients across Germany for years – as a single expert, as reinforcement for an existing team, or as a complete Scrum team.

Talk about your project →