useLayoutEffect
Your useLayoutEffect
callback/effects will be fired synchronously after all DOM mutations, i.e., before the browser has a chance to paint.
This can be useful if you need to make DOM measurements (like getting the scroll position or other styles for an element) and then make DOM mutations or trigger a synchronous re-render by updating state.
It is recommended that you use useEffect
when possible to avoid blocking visual updates. However, there are legitimate use cases for useLayoutEffect
, e.g., to read layout from the DOM and synchronously re-render.
If you are migrating code from a class component, useLayoutEffect
fires in the same phase as componentDidMount
and componentDidUpdate
, but start with useEffect
first, and only try useLayoutEffect
if that causes a problem. Don’t block visual updates except when you’re absolutely sure you need to.
It’s also worth mentioning that with server-side rendering, neither useEffect
nor useLayoutEffect
are run until JavaScript is downloaded on the client.
You’ll get a warning with server-rendered components containing useLayoutEffect
. To resolve this, you can either move the code to useEffect
, i.e., to be fired after first render (and paint), or delay showing the component until after the client renders.
It looks exactly like useEffect but different use-cases. Here is the syntax for it
Timing of an effect
There’s a very big difference between when the useEffect
callback is invoked and when class methods such as componentDidMount
and componentDidUpdate
are invoked.
The effect callback is invoked after the browser layout and painting are carried out. This makes it suitable for many common side effects, such as setting up subscriptions and event handlers since most of these shouldn’t block the browser from updating the screen.
This is the case for useEffect
, but this behavior is not always ideal.
What if you wanted a side effect to be visible to the user before the browser’s next paint? Sometimes, this is important to prevent visual inconsistencies in the UI,.
For such cases, React provides another Hook called useLayoutEffect
. It has the same signature as useEffect
; the only difference is in when it’s fired, i.e., when the callback function is invoked.
N.B., although
useEffect
is deferred until the browser has painted, it is still guaranteed to be fired before any re-renders. This is important.
React will always flush a previous render’s effect before starting a new update.
useEffect vs useLayoutEffect
useEffect (Component > State Changes > Component Renders > Rendered Component is Printed on Screen > useEffect runs)
useEffect will run after React renders your component and ensures that your effect callback does not block browser painting.
useLayoutEffect (Component > State Changes > Component Renders > useLayoutEffect runs > Rendered Component is Printed on Screen)
useLayoutEffect runs synchronously immediately after React has performed all DOM mutations.
Why Use useLayoutEffect
?
useLayoutEffect
?So if useLayoutEffect
will delay the painting of a component why would we want to use it. The biggest reason for using useLayoutEffect
is when the code being run directly modifies the DOM in a way that is observable to the user.
For example, if I needed to change the background color of a DOM element as a side effect it would be best to use useLayoutEffect
since we are directly modifying the DOM and the changes are observable to the user. If we were to use useEffect
we could run into an issue where the DOM is painted before the useEffect
code is run. This would cause the DOM element to be the wrong color at first and then change to the right color due to the useEffect
code.
You Probably Don't Need useLayoutEffect
useLayoutEffect
As you can see from the previous example, use cases for useLayoutEffect
are pretty niche. In general it is best to always use useEffect
and only switch to useLayoutEffect
when you actually run into an issue with useEffect
causing flickers in your DOM or incorrect results.
References and articles :
Last updated