I have an question about when will the useLayoutEffect
callback be triggered and when will the screen be drawn.
Consider the following code:
export default function CompA() {
const [count, setCount] = useState(0);
useLayoutEffect(() => {
// I'll debug here after initial render
console.log('CompA layoutEffectCallback');
});
useEffect(() => {
console.log('CompA updateEffectCallback');
}, [count]);
const handleClick = () => {
setCount(count + 1);
};
return (
<div onClick={handleClick}>
CompA
<h1>{count}</h1>
</div>
);
}
After the initial render, the screen displays the number 0,then I set a chrome devtool debugger in the callback of the useLayoutEffect
hook before I click the div. After click, the function execution is paused at debugger, but I see the screen already shown number 1.
The docs said that useLayoutEffect
fires before the browser repaints the screen,but I don’t understand why the screen has updated.
2
Answers
The
useLayoutEffect
hook runs synchronously after the DOM is updated but before the browser repaints.Initially, you rendered
CompA
, and the initial state ofcount
was 0. Then, you clicked thediv
andcount
was increased to 1.Since
useLayoutEffect
is ran after the DOM has been updated BUT before it repaints, the layout effect will logCompA layoutEffectCallback
right before the browser performs the paint. This is why you see the screen showing "1" even when the debugger is paused inuseLayoutEffect
. The DOM has already been updated with the new state before the browser is notified to render it.Pausing/break-pointing in the
useLayoutEffect
callback doesn’t prevent/block the browser from repainting. It’s merely a place you can "hook" into and apply some logic like measuring the computed DOM before the browser repaints. You will still see the updated DOM and repainted view regardless.Here’s a handy, albeit a bit outdated, diagram of the React component lifecycle:
useLayoutEffect
is called in roughly the "pre-commit phase" where it can check the computed DOM.useEffect
would be called later/after the "commit phase".