Is `useLayoutEffect` preferable to `useEffect` when reading layout?

Viewed 1174

One difference about useLayoutEffect vs useEffect is that useLayoutEffect will be fired synchronously after DOM mutation and before the browser paint phase. (Reference)

However, I've came across some articles and they all seem to recommend to use useLayoutEffect for reading layout.

React docs:

The signature is identical to useEffect, but it fires 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.

Kent C.Dodds:

useLayoutEffect: If you need to mutate the DOM and/or do need to perform measurements.

Ohans Emmanuel:

Where possible, choose the useEffect Hook for cases where you want to be unobtrusive in the dealings of the browser paint process. In the real world, this is usually most times! Well, except when you’re reading layout from the DOM or doing something DOM-related that needs to be painted ASAP.

As I understand, by the time the useEffect is fired, the browser has already passed the layout and paint phase, so reading layout in useEffect should be totally okay.

So my question: Is useLayoutEffect preferable to useEffect when reading layout and if yes, why? Taken that I just only read the layout and don't perform any additional state changes in the effect.

3 Answers

The following diagram always helps me to visualize the flow of hooks and also will let you clarify regarding why useLayoutEffect is recommended over useEffect for DOM based operations (where you're targetting stuff that you can update before current browser paint)

Link to the diagram - https://github.com/donavon/hook-flow

If you don't have DOM manipulating code in the hook and only reading layout useEffect will do just fine.

If you do have DOM manipulating code in the useEffect and see screen flickering move this code to useLayoutEffect.

It goes like this:

  1. Render
  2. useLayoutEffect (synchronously after all DOM mutations)
  3. Paint
  4. useEffect

The answer depends on what you as a developer consider 'preferable'. In the context of your question useLayoutEffect guarantees that you will see layout before mutation, useEffect shows you what happens after.

Related