useLayoutEffect & useInsertionEffect
Measure and correct before the browser paints
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.
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.
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
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>;
} - +
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
- −
Everything else –
useEffectis the default - −
Loading data, subscriptions, timers
- −
Server rendering: it does not run there and warns in the console
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.
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.