Interview frequency: …
Short answer
useLayoutEffect runs synchronously after the DOM changes and before the browser paints, while useEffect runs asynchronously after the browser finishes painting.
Explanation
If code measures a DOM element and changes its appearance (such as Tooltip position or scroll), running it in useEffect can cause visible Flicker because the browser paints first and React changes the UI afterward. useLayoutEffect blocks browser painting until its synchronous code finishes, so the final change appears all at once.
Code example
useLayoutEffect(() => {
const rect = tooltipRef.current?.getBoundingClientRect();
if (rect) {
setPosition({ top: rect.bottom + 8, left: rect.left });
}
}, []);Common mistakes
- Overusing useLayoutEffect for ordinary tasks such as fetching data, blocking browser painting and responsiveness.