DEV Community

Cover image for Performant React 101: `useEffect` or `useLayoutEffect`?
James Won
James Won

Posted on

Performant React 101: `useEffect` or `useLayoutEffect`?

Front-end developers working with React use the useEffect hook all the time to render side-effects.
 
But did you know that there is a similar but slightly different hook called useLayoutEffect? I didn't, until I stumbled on an instance of this hook used in one of the codebases I was contributing to.

This is a blog to get to the heart of the difference between the two and understand when and when not to use each.

The difference

In a nutshell the difference is about precision.

  • useEffect runs but there is no guarantee about exactly when this occurs. It is an asynchronous operation that runs after layout and painting of the pixels.

  • useLayoutEffect in contrast, is guaranteed to run immediately. It is a synchronous operation that occurs after all DOM mutations and before the browser can paint the pixels. If you are familiar with the componentDidMount lifecycle in React's class components, this is basically the equivalent behaviour.

useLayoutEffect seems superior. Should we use it for everything?

But why wouldn't we want to use useLayoutEffect all the time?

Not so fast. As with everything, precision has a cost.

React has optimised useEffect to be more performant. We need to program side-effects a lot when using React and the performance enhancements built into to useEffect will materially add up.

The React team explicitly encourages users to use useEffect as much as possible to avoid blocking visual updates.

In the words of the React official docs under 'Timing of effects':

… the function passed to useEffect fires after layout and paint, during a deferred event. This makes it suitable for the many common side effects, like setting up subscriptions and event handlers, because most types of work shouldn't block the browser from updating the screen.

Side note: The React team recently upgraded useEffect in React 18 to make it synchronous for common events such as a user clicks, even less reasons for you to use the useLayoutEffect hook.

So when should we use useLayoutEffect?

This usually boils down to one main reason:

When you need to measure the DOM and provide immediate visual feedback of the calculation (hence the 'Layout' in the name).

This is important here as side-effects cannot be deferred.

There is an additional use case: 

  • As I mentioned above, useLayoutEffect is the equivalent of the old componentDidMount lifecycle in React's class components. This hook can be used to help you migrate from class components to function components to give you a one-for-one replacement. However, this should be a temporary fix.

Takeaways

Think of useEffect as your reliable Toyota corolla: reliable, performant and cheap - perfect for 99.9% of use cases. useLayoutEffect on the other hand is a high-end Ferrari: fast, responsive, but costly to run reserved for the 0.1% when speed really matters.

  • useEffect and useLayoutEffect is both used to action side-effects, but the latter allows you more precise control when it is run.

  • Use useEffect as much as possible to take advantage of the React teams performance optimisations. There are very few genuine use cases for useLayoutEffect . Only use if (1) you need to visually show side-effects immediately to your users, or (2) when you are temporarily migrating from componentDidMount.

Discussion (0)