The difference is following.
useEffect runs asynchronously after the render is committed to the screen.
useLayoutEffect on the other hand based on docs runs:
synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render. Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.
Because of this if you update screen in useEffect you may notice some blink effect sometimes. Because screen was updated then you immediately updated it again in useEffect.
But most of the times you probably need useEffect. Docs:
Answer from gmoniava on Stack OverflowPrefer the standard useEffect when possible to avoid blocking visual updates.
reactjs - Is scrolling to bottom after render a good use case for useLayoutEffect? - Stack Overflow
What’s the best way to handle scroll with effects hooks?
Render a div in React with an initial scrollTop value set
Scroll restoration + useLayoutEffect not working
So I'm implementing scroll restoration in a component that I have. When I run the restoration logic in useEffect, it works, but there's a flash just before it sets the scroll position. This isn't surprising, seeing as useEffect is ran after the browser paints. So I moved the logic into useLayoutEffect to execute before the browser paints, but it doesn't work - I start off at scrollLeft = 0, rather than scrollLeft = whatever it was when I left the page.
I googled around and people reported that useLayoutEffect works for them. I'm not sure why it's not working for me.
I noticed that if I put my canvas.scrollLeft = prevCanvasPos; into a setTimeout (with 0 seconds), it works - except there's a flash. I'm not surprised at the flash, but this seems to indicate to me that it can't scroll to the position before the browser paints, even though the entire DOM is already constructed.
Here's the code:
useLayoutEffect(() => {
const canvas = canvasRef.current;
const prevCanvasPos: number | undefined = Number(
localStorage.getItem('canvasPos'),
);
if (prevCanvasPos && canvas) {
canvas.scrollLeft = prevCanvasPos;
}
function setCanvasPos() {
if (canvas) {
localStorage.setItem('canvasPos', String(canvas.scrollLeft));
}
}
window.addEventListener('beforeunload', setCanvasPos);
return () => {
if (canvas) {
localStorage.setItem('canvasPos', String(canvas.scrollLeft));
}
window.removeEventListener('beforeunload', setCanvasPos);
};
}, []);Any suggestions?