1
ReactIntermediate#effects#debugging
useEffect runs asynchronously after paint, so it never blocks visual updates. useLayoutEffect runs synchronously after DOM mutation but before paint, which is required for measuring layout to avoid flicker.
useLayoutEffect(() => {
const h = ref.current.getBoundingClientRect().height;
setHeight(h); // measured before the user sees it
}, []);