UseEffect vs UseLayoutEffect in React
Tags: react, webdev, javascript
Published: 2023-04-11 23:44:08

by [Ariochi Wuchegbule](https://blog.openreplay.com/authors/ariochi-wuchegbule)

Initially, when a component first loads and the state changes, it re-renders the `DOM` so we can update that state in the browser. The [UseEffect hook](https://reactjs.org/docs/hooks-effect.html) is a way to run code on every render, which can be useful for many reasons. The [UseLayoutEffect hook](https://beta.reactjs.org/reference/react/useLayoutEffect) is a hook you have probably never heard of, and if you have heard of it, you may not know when exactly to use it: this hook and the `UseEffect` hook are nearly identical. `UseLayoutEffect` differs from `useEffect()` because it is not asynchronous.

## Goals

This article will identify areas where `useLayoutEffect()` would be better than `UseEffect()`. We'll simplify the use of React's `useLayoutEffect()` and explain how to position it to maximize performance and speed up problem-solving. In the course of this tutorial, we will have to build a simple application that resembles the one below, built with the `useEffect()` hook:

![-](https://blog.openreplay.com/images/useeffect-vs-uselayouteffect-in-react/images/ucKQN1a.gif)

We will also recreate the above, using the `useLayoutEffect()` hook instead:

![-](https://blog.openreplay.com/images/useeffect-vs-uselayouteffect-in-react/images/nssDTU4.gif)

The differences observed in both apps built with `useEffect()` and `useLayoutEffect()` respectively will be the core reasons for this article.

## Utilizing UseLayoutEffect()

The `UseEffect()` and `useLayoutEffect()` hooks are mostly identical, and their syntax is the same as seen below;
```jsx
//useEffect()
useEffect(() => {
  setMessage('welcome to open replay blog')
}, [])

//useLayoutEfect
useLayoutEffect(() => {
  setMessage('welcome to open replay blog')
}, []) 
```


## Key differences between useLayoutEffect() and useEffect()

So, with their identical syntaxes, what is the difference between these two hooks? Well, there are three key differences: 
The asynchronous nature of `useEffect`
The `DOM` flashes
The fact that `useLayoutEffect` is executed before `useEffect`.

`UseEffect()` is asynchronous by nature: it will not delay painting the `DOM` to the browser, but on the other hand, the `useLayoutEffect()` hook is synchronous, and it will delay painting the `DOM` to the browser. It runs its code before painting to the browser. So when does this come in handy? Well, it makes the `useEffect()` hook the correct and more performant choice about 95% of the time.

However, just that 5% percent of the time `useLayoutEffect()` has, it takes full advantage of its potential. When you want to choose `useLayoutEffect` over `useEffect` and that is because you will want the code to run before it directly modifies the `DOM` and that modification, of course, is observable to the user, you don't want the user to observe that change, and that brings us back to the example that I gave at the beginning of this tutorial.

If you notice, whenever I click the button, the number changes, and the whole section element tends to move, but this is observable to the user. What I do want to do, as seen in the second GIF in the application demo, is have the element move but without displaying the change in number until it has moved.


<h2>Session Replay for Developers</h2> 
<p><em>
Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data
</em></p>
<img alt="OpenReplay" width="768" height="400" src="https://blog.openreplay.com/assets/overview_Z17Qdyg.png" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em>






## A short demo

Here is the code for the demo;
```jsx
import { useState, useRef, useEffect, useLayoutEffect } from 'react';

function App() {
  const [count, setCount] = useState(0);
  const [elementStyle, setElementStyle] = useState({});
  const elementRef = useRef();

  useEffect(() => {
    const atRandom = Math.floor(Math.random()*500)-50;

    for (let i = 0; i <= 100000000; i++) {
      if (i === 100000000) setElementStyle({ paddingTop: `${atRandom}px` })
    }
  }, [count])
/*the loop above just serves to make the changes in this example visible by slowing them down */

  return (
    <div className="app">
      <div ref={elementRef} style={elementStyle}>
        <p>{count}</p>
        <div>
          <button onClick={() => setCount(prev => prev + 6)}>+</button>
        </div>
      </div>
    </div>
  ); 
}
export default App;
```
We should be able to have the GIF below after basic styling
```css
.btn{
    background-color: rgb(250, 197, 119);
    border: none;
    color: white;
    padding: 15px 32px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;    
}
.app{
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center; 
}
.p{
  text-align: center; 
  text-decoration: none;
  font-size: 16px;    
}
```
![-](https://blog.openreplay.com/images/useeffect-vs-uselayouteffect-in-react/images/q9oMCZA.gif)

We need to modify the code with `useLayoutEffect()`; this is what it looks like:
```jsx
useLayoutEffect(() => {
  const atRandom = Math.floor(Math.random()*500)-50;

  for (let i = 0; i <= 1000000; i++) {
    if (i === 1000000) setElementStyle({ paddingTop: `${atRandom}px` })
  }
}, [count])
```
You can see the difference:
![-](https://blog.openreplay.com/images/useeffect-vs-uselayouteffect-in-react/images/QCtdHCu.gif)

`DOM` Flashes, another key difference to note here that comes in handy is if you see a flash effect on the screen numerous times, you are changing several things in the `DOM` that take a while to process. Therefore, you may see that flash when the repaint happens, like the code below prints:
```jsx
import React, { useState, useEffect, useLayoutEffect } from 'react';
import './App.css';
function App() {
  const [message, setMessage] = useState("hello dev's");

  useEffect(() => {
   setMessage('welcome to open replay blog')
  }, [])
  return (
    <div className="container">
      <h2>{message}</h2>
    </div>
  );
}
export default App;
```
Replacing the code below with `useLayoutEffect()` returns a different result that solves the flashes. `UseLayouEffect()` runs before `useEffect()`: this last key difference is minor but still important. Similar to the first difference indicated, `useLayouEffect()` runs before `useEffect()`.
```jsx
import React, { useState, useEffect, useLayoutEffect } from 'react'
import './App.css'
function App() {
  const [message, setMessage] = useState("hello dev's")
  useEffect(() => {
    setMessage('welcome to open replay blog')
    console.log(message)
  }, []) 

  useLayoutEffect(() => {
    setMessage('welcome to open replay blog')
    console.log(message)
  }, [])
```
Image:
![-](https://blog.openreplay.com/images/useeffect-vs-uselayouteffect-in-react/images/V6OEZxw.png)

As we can see above, the useLayouteffect code always comes before `useEffect`.

## Conclusion

Generally speaking, it is best to always use `useEffect` and only switch to `useLayoutEffect` if `useEffect` genuinely creates flickering in your DOM or produces an inaccurate result. Although `useLayoutEffect` is a very helpful hook in some circumstances, `useEffect` will work just fine most of the time. Additionally, if `useEffect` functions well, it is preferable to use it because it does not prevent painting.




[![newsletter](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)