React executes the useEffect hook asynchronously after the real dom is rendered. On the other hand, the execution of the useLayoutEffect hook happens synchronously before the real dom is rendered.
In other words, the useEffect hook does not block browser painting, while the useLayoutEffect does.
useEffect hook life cycle
Component mounts or re-renders
Virtual DOM mutations take place
Real DOM syncs with the virtual DOM (paints the contents on the screen)
Executes useEffect hooks
The useEffect hook execution happens after the real dom is painted. Any method calls inside the useEffect are asynchronous as well. Therefore, the useEffect hook does not block the rendering process.
useLayoutEffect hook life cycle
Component mounts or re-renders
Virtual DOM mutations take place
Executes useLayoutEffect hooks
Real DOM syncs with the virtual DOM (paints the contents on the screen)
The useLayoutEffect hook execution happens before the real dom is painted. Therefore, it blocks the actual DOM rendering process. Any method calls inside the useLayoutEffect are synchronous as well.
Here is a simple example to illustrate the execution order of each hook.
The useLayoutEffect hook blocks the UI. It is synchronous, and any method calls inside the useLayoutEffect hook are also synchronous.
It is useful when I have to manipulate the DOM directly. Such as adding or removing DOM elements. The reason to perform the DOM manipulations inside the useLayoutEffect is to make the changes invisible to the user because we see the real DOM after the useLayoutEffect is done. Of course, we can use the useEffect hook for this case, but the DOM manipulations may become visible.