React useLayoutEffect vs useEffect with examples
Tags: react, webdev, javascript, tutorial
Published: 2023-08-23 00:52:37

In this article, we are going to learn about useEffect vs useLayoutEffect.

**Introduction**

* [React Hooks: An Introduction](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#react-hooks-an-introduction)
    
* [Side Effects in React : useEffect and useLayoutEffect](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#side-effects-in-react-useeffect-and-uselayouteffect)
    

II. [**useEffects**](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#understanding-useeffect)

* [Syntax](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#syntax-and-basic-usage)
    
* [Example: Fetching data with `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-fetching-data-with-useeffect)
    
* [Clean Up function in  `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#clean-up-function)
    
* [Dependency Array](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#dependency-array)
    

III. [**useLayoutEffect**](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#uselayouteffect)

* [What is  `useLayoutEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#uselayouteffect)
    
* [Syntax](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#syntax)
    
* [Example: using `useLayoutEffect` to synchronise DOM changes](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-using-uselayouteffect-to-synchronise-dom-changes)
    
* [Clean Up function  in `useLayoutEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#clean-up-function-in-uselayouteffect)
    
* [Dependency array in `useLayoutEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#dependency-array-in-uselayouteffect)
    

IV. [**Difference between useLayoutEffect and useEffect**](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#difference-between-uselayouteffect-and-useeffect)

* [(asynchronous vs synchronous) Timing of execution](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#asynchronous-vs-synchronous-timing-of-execution)
    
* [Use-Case for useLayoutEffect and useEffect](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#use-case-for-uselayouteffect-and-useeffect)
    

V. [**Examples: When to use useEffect and useLayoutEffect**](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#examples-when-to-use-uselayouteffect-and-when-to-use-useeffect)

* [Example 1: Updating the DOM based on a state change](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-1-updating-the-dom-based-on-state-changes)
    
* [Example using `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#useeffect)
    
* [Example using  `useLayoutEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#uselayouteffect-1)
    
* [Example 2: Updating the DOM and Measuring the DOM](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-2-updating-the-dom-and-measuring-the-dom)
    
* [Example using `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#useeffect-1)
    
* [Example using `useLayoutEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#uselayouteffect-2)
    
* [Example 3: Fetching user data with useEffect](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-3-fetching-user-data-with-useeffect)
    
* [Example 4: Sync the height of 2 elements with the help of useLayoutEffect](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#example-4-sync-the-height-of-2-elements-with-the-help-of-uselayouteffect)
    

VI. [**Best Practices and When to use** `useLayoutEffect` and `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#best-practices-and-when-to-use-uselayouteffect-and-useeffect)

* [When to choose `useLayoutEffect` and `useEffect`](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#when-to-choose-uselayouteffect-and-useeffect)
    
* [Tips for optimizing performance](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#tips-for-optimizing-performance)
    
* [Common mistakes and how to avoid them](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#common-mistakes-and-how-to-avoid-them)
    

VII. [**Conclusion**](https://deadsimplechat.com/blog/uselayouteffect-vs-useeffect-with-examples/#conclusion)

* Thank you for reading
    

## React Hooks: An Introduction

React hooks are simple JavaScript functions that enable developers to use state and other react features in functional components

They encapsulate re-useable code in functions, that can be added in components to introduce functionality that was previously available in class components into functional components

Some common hooks include `useState` , `useEffect`, `useContext` and `useLayoutEffect`

The hooks enable developers to handle side effects, manage local state and read and access context

This article is provided by DeadSimpleChat [Chat API](https://deadsimplechat.com) for your website and app

By using Hooks developers can create a more readable, concise and maintainable codebase

## Side Effects in React: useEffect and useLayoutEffect

Components need to synchronize with external systems, like setting up a server connection, controlling an external library based on react state etc

Here are some of the reasons why managing side effects is important in react

1. Ability to predict and maintain code: Properly handling effects results in fewer bugs and more reliable code, thus app behaves predictably and it is easier to maintain as well
    
2. Ability to Optimize performance: Proper management of effects results in optimization of performance and resource utilization
    
3. Cleanup functionality: With proper effects hook you can easily write the code to clean up as well after the effects have taken place
    
4. Synchronization: With effects hooks, you can synchronize component lifecycle events with effects.
    

`useEffect` and `useLayoutEffect` are two react hooks that provide a way to perform side effects, sync with component lifecycle and clean up after the effect has taken place

`useEffect`

useEffect is a hook that lets you handle side effects in react.

Components need to connect to the network, call an API or sync with a third-party library or other asynchronous operations.

All of these are not controlled by react and hence are called external systems

`useEffect` is used to connect, sync and control external systems. `useEffect` runs after the component has rendered on the screen and it can be setup to re-run on every render or when some dependencies change

**useLayoutEffect**

`useLayoutEffect` is similar to useEffect but it runs synchronously after all the DOM but before the browser has rendered anything on the screen

You can use this hook to measure or manipulate the DOM and want to ensure the changes are made before the browser repaints

## Understanding useEffect

React `useEffect` is a react hook that lets you perform side effects in react.  With useEffect you can connect to external systems like connect to the network or server, a third party library.

### Syntax and Basic usage

```javascript
useEffect(() => {
  // write logic to handle side effect like callling an API /connecting to a server or connecting to a third party library here

  return () => {
    // You can create a cleanup function to clean up after the effect has taken place
  };
}, [dependencyA, dependencyB]);
```

`useEffect` has the following

1. A function that contains the logic to handle side effect
    
2. An optional dependency array, that has dependencies listed, When the dependencies change, the effect reruns
    
3. An optional cleanup function that cleans up after the effect has taken place
    

### Example: Fetching data with useEffect

In this example, we are going to fetch some data using an API and the useEffect hook

```javascript
import React, { useState, useEffect } from 'react';

function GetDetails() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function getInfo() {
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
      const data = await response.json();
      setData(data);
      setLoading(false);
    }

    getInfo();
  }, []); // If you want the code to run only once when mounted leave the dependency array empty

  return (
    <div>
      {loading ? <p>searching...</p> : <ul>{data.map(item => <li key={item.id}>{item.title}</li>)}</ul>}
    </div>
  );
}
```

### Clean Up function

As I have already stated the clean-up function is an optional function that can be returned from the `useEffect`

It is used to perform clean-up after the effect has taken place, this might include unsubscribing from events, or releasing resources.

Here is an example of using a clean-up function to unsubscribe from a WebSocket connection

```javascript
import React, { useState, useEffect } from 'react';

function SocketConnection() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const socket = new WebSocket('wss://demo.piesocket.com/v3/channel_123?api_key=VCXCEuvhGcBDP7XhiJJUDvR1e1D3eiVjgZ9VRiaV&notify_self');

    socket.onmessage = (event) => {
      setMessages((prevMessages) => [...prevMessages, event.data]);
    };

    return () => {
      socket.close();
    };
  }, []); // To run the effect only once during mounting leave the dependency array empty

  return (
    <ul>
      {messages.map((message, index) => (
        <li key={index}>{message}</li>
      ))}
    </ul>
  );
}
```

Clean up function

### Dependency Array

It is an optional second argument in useEffect. It is an array of dependencies, when these dependencies change it triggers a re-run of the effects

If the empty array is provided the effect will run only once when the component mounts

If the array is omitted then the effects run every time the component is rendered

let us consider an example:

```javascript
import React, { useState, useEffect } from 'react';

function UserData({ userId }) {
  const [data, setData] = useState(null);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(`https://api.example.com/users/${userId}`);
      const data = await response.json();
      setData(data);
    }

    fetchData();
  }, [userId]); // Effect runs whenever the userId prop changes
```

useEffects

## uselayoutEffect

`useLayoutEffect` is a react hook similar to `useEffect` with function that has a the side effect logic, a dependency array and an optional callback function can be returned as well

The difference between useLayoutEffect and useEffect is that `useLayoutEffect` runs synchronously after all the DOM mutations and before the browser repaints

This hook can be used to measure and manipulate the DOM and when we want to ensure that the changes have been made before the browser repaints. This involves use-cases which might cause flickering or layout jumps

The `useLayoutEfffect` should be used when necessary because it can cause performance issues, because of its synchronous nature

### Syntax

`useLayoutEffect` has a similar syntax as useEffect

```javascript
useLayoutEffect(() => {
  // Some effect logic goes here

  return () => {
    // optional clean up function
  };
}, [dependencyA, dependencyB]);
```

### Example: using useLayoutEffect to synchronise DOM changes

In this example, we are going to update the position of the tooltip based on the position of the target element

```javascript
import React, { useRef, useLayoutEffect } from 'react';

function ToolTipLocator({ targetRef, children }) {
  const tooltipRef = useRef();

  useLayoutEffect(() => {
    const targetRect = targetRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();

    tooltipRef.current.style.left = `${targetRect.left + (targetRect.width - tooltipRect.width) / 2}px`;
    tooltipRef.current.style.top = `${targetRect.top - tooltipRect.height}px`;
  }, []);

  return (
    <div ref={tooltipRef} className="tipOfTheTool">
      {children}
    </div>
  );
}
```

DOM changes in useLayoutEffect

In this example we are using the `useLayoutEffect` to update the tooltip's position with respect to the target element

### Clean Up function  in useLayoutEffect

Clean up function is exactly similar to the useEffect, so you can just reference it in from above. Just replace `useEffect` with `useLayoutEffect`

### Dependency array in useLayoutEffect

Dependency Array is exactly similar to the useEffect, so you can just reference it from above. Just replace `useEffect` with `useLayoutEffect`

## Difference between useLayoutEffect and useEffect

### Asynchronous vs synchronous timing of execution

The core difference between useLayoutEffect and useEffect is the timing of the execution of code

while the useEffect is asynchronous the useLayoutEffect is synchronous

* `useEffect`: The useEffect runs after the component has been rendered and is an asynchronous hook, primarily used to handle external systems like api calls or integration with third-party library
    
* `useLayoutEffect` : The useLayoutEffect is a synchronous hook, that runs after all the DOM mutations but before the browser layout. It is mainly used for UI and it may cause performance issues as it blocks the browser from painting the UI until the effects have taken place. It is used to avoid issues like flickering or jumps in the UI
    

## Use-Case for useLayoutEffect and useEffect

Here are some of the common use-cases for both of these hooks

`useEffect`

* Connecting to a remote server
    
* Fetching data from an API
    
* Updating the state in response to prop changes
    
* connecting to external third-party libraries
    
* Performing other asynchronous operations
    

`useLayoutEffect`

* When state changes updating the DOM
    
* Preventing flickering or UI Jumps during DOM manipulations
    
* Sync DOM changes with other components or UI elements
    

## Examples: When to use useLayoutEffect and when to use useEffect

### Example 1:  Updating the DOM based on state changes

#### useEffect

In this example we have a component that displays a list of items and a toggle button to show/ hide the visibility of the list

We can use useEffect to update the visibility of the list based on the state changes

```javascript
import React, { useState, useEffect } from 'react';

function TogglableList() {
  const [isVisible, setIsVisible] = useState(true);

  useEffect(() => {
    const listElement = document.getElementById('user-list');

    if (isVisible) {
      listElement.style.display = 'block';
    } else {
      listElement.style.display = 'none';
    }
  }, [isVisible]);

  return (
    <div>
      <button onClick={() => setIsVisible(!isVisible)}>Show / Hide list</button>
      <ul id="user-list">
        {/* List of items goes here */}
      </ul>
    </div>
  );
}
```

Here we are using the `useEffect` to update the show/hide property of the list using the `isVisible` state

Here DOM update is not critical to the calculations of layout or to asynchronous operation with `useEffect` hook

#### useLayoutEffect

Now, let us consider an example where visibility changes require a synchronous operation and we need to use useLayoutEffect

Consider a component that measures the height of a panel that can collapse and we are animating the height based on the `isExpanded` state

```javascript
import React, { useState, useLayoutEffect } from 'react';

function PanelThatCanCollapse({ children }) {
  const [isExpanded, setIsExpanded] = useState(false);

  useLayoutEffect(() => {
    const panelElement = document.getElementById('collapsible-panel');

    if (isExpanded) {
      const heightOfThePanel = panelElement.scrollHeight;
      panelElement.style.height = `${heightOfThePanel}px`;
    } else {
      panelElement.style.height = '0';
    }
  }, [isExpanded]);

  return (
    <div>
      <button onClick={() => setIsExpanded(!isExpanded)}>Show / Hide</button>
      <div id="collapsible-panel" className="collapsible-panel">
        {children}
      </div>
    </div>
  );
}
```

height adjustment using useLayoutState

Here we are using the useLayoutEffect because the `useLayoutEffect` synchronously updates the height of the panel before the browser paints

We need the height update to be made synchronously because otherwise it would break the UI for a little time and that would be a bad experience for the user.

In short, where the UI would break we need synchronous effect resolution thus we use `useLayoutEffect` other wise we use `useEffect`

### Example 2: Updating the DOM and Measuring the DOM

We are considering an example where we will measure the DOM and update the DOM based on the measurements

#### useEffect

We have a component which displays a notification, we need to center it horizontally in the screen.

We can use `useEffect` to measure the length of the notification bar and update its position to center it on the screen

```javascript
import React, { useState, useEffect } from 'react';

function Toast({ toastMessage }) {
  const [leftPosition, setLeftPosition] = useState(0);

  useEffect(() => {
    const toastElement = document.getElementById('toast');
    const toastWidth = toastElement.offsetWidth;
    const screenWidth = window.innerWidth;

    setLeftPosition((screenWidth - notificationWidth) / 2);
  }, [message]);

  return (
    <div id="toast" className="toast" style={{ left: leftPosition }}>
      {toastMessage}
    </div>
  );
}
```

center the toast in the center of the screen

In this example we are using `useEffect` to measure the width of the toast notification based on the width of the screen.

Since measurement and updating the position are not critical to rendering the UI on the page we can use `useEffect` to manage this.

#### useLayoutEffect

In this example we have a tolltip next to an input field, and we want to ensure that the tooltip is propperly positioned before the browser repaints

```javascript
import React, { useRef, useLayoutEffect } from 'react';

function InputTooltip({ textOfTooltip }) {
  const inputRef = useRef();
  const tooltipRef = useRef();

  useLayoutEffect(() => {
    const inputRect = inputRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();

    tooltipRef.current.style.left = `${inputRect.right + 20}px`;
    tooltipRef.current.style.top = `${inputRect.top + (inputRect.height - tooltipRect.height) / 2}px`;
  }, [TextOfTooltip]);

  return (
    <div>
      <input ref={inputRef} type="text" />
      <div ref={tooltipRef} className="tooltip">
        {textOfToolTip}
      </div>
    </div>
  );
```

In this example we are using `useLayoutEffect` to synchronously position the tooltip next to the input field

We are using `useLayoutEffect` because we need the tooltip exactly next to the input field when the page renders on the screen, if the tooltip comes at a later point in time it might cause issues like UI jumps.

### Example 3: Fetching user data with useEffect

We are building a component that fetches the user data from an API when the component mounts

```javascript
import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [userData, setUserData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    async function fetchData() {
      const response = await fetch(`https://jsonplaceholder.typicode.com/users`);
      const data = await response.json();
      setUserData(data);
      setLoading(false);
    }

    fetchData();
  }, [userId]);

  return (
    <div>
      {Searching ? (
        <p>Searching...</p>
      ) : (
        <div>
          <h1>{userData.name}</h1>
          <p>Email: {userData.email}</p>
          {/* list of user details here */}
        </div>
      )}
    </div>
  );
}
```

Here we are using the `useEffect` to fetch the user data from the JSON placeholder website and render it when the component mounts.

We have also added userId as a dependency, so when ever the userId gets upadated the effects run again thus calling the API again to update the user details

we are also displaying the user data or a seaching indicator based on the state of the component at that point in time

### Example 4: Sync the height of 2 elements with the help of useLayoutEffect

We have 2 elements on a page and we want to make their heights in sync with each other such that they are always equal

```javascript
import React, { useRef, useLayoutEffect } from 'react';

function InSyncHeight({ leftColumn, rightColumn }) {
  const leftRef = useRef();
  const rightRef = useRef();

  useLayoutEffect(() => {
    const leftHeight = leftRef.current.offsetHeight;
    const rightHeight = rightRef.current.offsetHeight;

    if (leftHeight > rightHeight) {
      rightRef.current.style.height = `${leftHeight}px`;
    } else {
      leftRef.current.style.height = `${rightHeight}px`;
    }
  }, [leftColumn, rightColumn]);

  return (
    <div className="InSyncHeight">
      <div ref={leftRef} className="column-left">
        {leftColumn}
      </div>
      <div ref={rightRef} className="column-right">
        {rightColumn}
      </div>
    </div>
  );
}
```

Here we are using `useLayoutEffect` to measure the height of both the colums and then set the height of the smaller column to match the height of the taller column

we have also added both the column variables in the dependency array such that whenver the height of any of these colums changes then the useLayoutEffect will run again

## Best Practices and When to use `useLayoutEffect` and `useEffect`

### When to choose useLayoutEffect and useEffect

`useEffect` runs asynchronous and does not cause any performance issues and thus should be the default choice whenever you want to deal with external systems such as

* calling an API
    
* updating DOM based on state changes
    
* connecting with a remote server
    
* connecting with third party library
    

Only for things that might cause an UI issue such as flickerring or UI jumps if the operation or connection with the external system is performed asynchronously then `useLayoutEffect` should be used

use the `useLayoutEffect` in the following scenarios

* When measuring or manipulating the DOM you need to make sure that *Changes are made before the browser repaints*
    
* *Effects must be in sync with the component rendering* to avoid momentary breaks in UI rendering.
    

### Tips for optimizing performance

* use the dependency array to control when the effects runs
    
* Avoid performance resource intensive tasks in `useLayoutEffect` as this would slow down the UI rendering, whenever the effect re runs
    
* Properly run the clean up function when the effects have run. As not performing proper clean-up might result in bugs or memory leaks
    
* Try to encapsulate complex logic in custom hooks
    

### Common mistakes and how to avoid them

1. **Not managing the dependency Array:** Remember these points with regard to the dependency array
    

Always state the reactive values in the dependency array, when reactive values change the effect will re-run

Leaving the dependency array empty will result in the effect running only once when the component mounts

Not providing the dependency array results in the effects running every time the component reruns

2\. **Overusing** `useLayoutEffect`

Only use the `useLayoutEffect` where it is necessary, defaulting to `useEffect` whenever possible. As `useLayoutEffect` is synchronous it may cause performance issues and it is render blocking as well. So, to avoid performance issues always default to `useEffect`

3\. **Always list reactive values in the dependency array**

Whenever you are using component values that are reactive, always list them in the dependency array. This ensures that whenever these values change the effect will run

1. **Not running the clean-up function properly or not running the clean-up function at all**
    

Clean up function is an important part of the effects, after the effects have taken place always free up the resources and clean up. Not doing the cleanup properly may cause bugs or memory leaks

## Conclusion

I hope you liked the article. Thank you for reading.

This article is brought to you by DeadSimpleChat, Chat API for your website and app