There are two React hooks, useEffect and useLayoutEffect , that appear to work pretty much the same.

The way you call them even looks the same.

useEffect (() => { // do side effects return () => /* cleanup */ } , [dependency, array] ) ; useLayoutEffect (() => { // do side effects return () => /* cleanup */ } , [dependency, array] ) ;

But they’re not quite the same. Read on for what makes them different and when to use each. (tl;dr: most of the time you want plain old useEffect )

The Difference Between useEffect and useLayoutEffect

It’s all in the timing.

useEffect runs asynchronously and after a render is painted to the screen.

So that looks like:

You cause a render somehow (change state, or the parent re-renders) React renders your component (calls it) The screen is visually updated THEN useEffect runs

useLayoutEffect , on the other hand, runs synchronously after a render but before the screen is updated. That goes:

You cause a render somehow (change state, or the parent re-renders) React renders your component (calls it) useLayoutEffect runs, and React waits for it to finish. The screen is visually updated

99% of the time, useEffect

Most of the time your effect will be synchronizing some bit of state or props with something that doesn’t need to happen IMMEDIATELY or that doesn’t affect the page visually.

Like if you’re fetching data, that’s not going to result in an immediate change.

Or if you’re setting up an event handler.

Or if you’re resetting some state when a modal dialog appears or disappears.

Most of the time, useEffect is the way to go.

Success! Now check your email. I put together a cheatsheet with different use cases for useEffect, and how they match up with lifecycle methods! Drop your email to get it delivered to your inbox. There was an error submitting your subscription. Please try again. Email Address Before we go on, I have to ask... consent

There was an error submitting your subscription. Please try again.

When to useLayoutEffect

The right time to useLayoutEffect instead? You’ll know it when you see it. Literally ;)

If your component is flickering when state is updated – as in, it renders in a partially-ready state first and then immediately re-renders in its final state – that’s a good clue that it’s time to swap in useLayoutEffect .

This’ll be the case when your update is a 2-step (or multi-step) process. Do you want to “batch” a couple updates together before redrawing the screen? Try useLayoutEffect .

I think of useLayoutEffect as the way to squeeze in a little extra work before React updates the DOM. “Hey, you’re making some changes already – could you throw this one in there too? Awesome.”

Here’s a (contrived) example so you can see what I mean.

When you click the page*, the state changes immediately ( value resets to 0), which re-renders the component, and then the effect runs – which sets the value to some random number, and re-renders again.

The result is that two renders happen in quick succession.

import React, { useState, useLayoutEffect } from 'react' ; import ReactDOM from 'react-dom' ; const BlinkyRender = () => { const [ value , setValue ] = useState ( 0 ) ; useLayoutEffect (() => { if ( value === 0 ) { setValue ( 10 + Math . random () * 200 ) ; } } , [value] ) ; console . log ( 'render' , value ) ; return ( < div onClick = { () => setValue ( 0 ) } > value: { value } </ div > ) ; } ; ReactDOM . render ( < BlinkyRender /> , document . querySelector ( '#root' ) ) ;

* In general, putting onClick handlers on div s is bad for accessibility (use buttons instead!), but this is a throwaway demo. Just wanted to mention it!

Try the useLayoutEffect version and then try the version with useEffect.

Notice how the version with useLayoutEffect only updates visually once even though the component rendered twice. The useEffect version, on the other hand, visually renders twice, so you see a flicker where the value is briefly 0 .

Should I useEffect or useLayoutEffect?

Most of the time, useEffect is the right choice. If your code is causing flickering, switch to useLayoutEffect and see if that helps.

Because useLayoutEffect is synchronous a.k.a. blocking a.k.a. the app won’t visually update until your effect finishes running… it could cause performance issues like stuttering if you have slow code in your effect. Coupled with the fact that most effects don’t need the world to pause while they run, regular useEffect is almost always the one to use.

Success! Now check your email. Learn the basics of React in 5 days Finally understand how React works! You will: 🎉 Get something on screen 💄 Write dynamic components 🏃 Make it interactive 😎 Fetch real data 🛳 Put it online 5 days, 5 emails. Walk away with the basics and a plan! Get Lesson 1 right now 👇 There was an error submitting your subscription. Please try again. Email Address I respect your email privacy. Unsubscribe any time. Before we go on, I have to ask... consent

There was an error submitting your subscription. Please try again.