React hooks - useLayoutEffect

Photo by Andrew Neel on Unsplash

React hooks - useLayoutEffect

Introduction

We all know about the useEffect. Let us look at a new hook called "useLayoutEffect" which works strikingly similar to the useEffect hook but with a minor difference.

The "useLayoutEffect" hook

useLayoutEffect is the same as the useEffect hook as both of them allows the developer to write code for executing side effects for rendering a component. So where is the difference then you may ask.

The difference lies in the way the operation is carried out.

The fundamental thing about useEffect is that the code inside it is run asynchronously. This means, the code inside useEffect is run only after the component has completed its rendering, i.e. everything in the DOM is painted onto the screen.

UseLayoutEffect, on the other hand, runs synchronously. This means the code in useLayoutEffect runs after the evaluation of the changes in the DOM is done but before the DOM is painted on the screen.

Now the question is if both of them are very similar, then when to use useLayoutEffect over useEffect?

One can see very carefully that useLayoutEffect runs synchronously and so it can cause performance issues in the application when overused. It is advisable to use useEffect and only use useLayoutEffect if the underlying problem cannot be resolved using useEffect hook.

That being out of the way, let us look into the possible use cases of the useLayoutEffect hook.

Whenever we write a piece of code that directly affects the UI in a way that is observable to the user, then in those cases using useLayoutEffect is better than using useEffect, for we want the DOM to update only after the execution of the side-effects in useLayoutEffect.

Let us look at an example to understand it in depth.

import { useLayoutEffect, useState, useRef } from "react";

export default function App() {
    const [ data, setData ] = useState([]);
    const popUpRef = useRef(null);
    const bottomRef = useRef(null);

    useLayoutEffect(() => {
        if(popUpRef.current === null || bottomRef.current === null) return;
    const { bottom } = bottomRef.current.getBoundingClientRect();
    popUpRef.current.style.top = `${bottom + 25}px`;
    }, [display]);

    return (
        <>
      <button ref={bottomRef} onClick={() => setDisplay(prev => !prev)}>
        Click here
      </button>
      {
        display && (
          <div style={{position: "absolute"}} ref={popUpRef}>
            This is a popup.
          </div>
        )
      }
    </>
    );
}

//P.S. The example is taken from "Wev Dev Simplified Blog" by Kyle. I will attach the link to the blog below

If you run the application, you can observe an issue where the position of the "This is a popup" text changes in a split second. Explaining this issue through text would be difficult so it’s better if you go and watch the original video on Youtube by Kyle from "Web Dev Simplified".

( P.S. don’t forget to hit the subscribe button and like his video. He makes really good videos on web development. )

( P.S. This is not a promotional blog. I just mentioned his name because I like what he does for the coding community. )

import { useLayoutEffect, useState, useRef } from "react";

export default function App() {
    const [ data, setData ] = useState([]);
    const popUpRef = useRef(null);
    const bottomRef = useRef(null);

    useLayoutEffect(() => {
        if(popUpRef.current === null || bottomRef.current === null)     return;
        const { bottom } = bottomRef.current.getBoundingClientRect();
        popUpRef.current.style.top = `${bottom + 25}px`;
        }, [display]);

    return (
        <>
      <button ref={bottomRef} onClick={() => setDisplay(prev => !prev)}>
        Click here
      </button>
      {
        display && (
          <div style={{position: "absolute"}} ref={popUpRef}>
            This is a popup.
          </div>
        )
      }
    </>
    );
}

//P.S. This example is also taken from Kyle's blog at "Web Dev Simplified"

useLayoutEffect in the above example solves the underlying issue that we observed in the video link above.

I have attached the link to Kyle's blog and his youtube channel below for your reference.

Kyle's blog - Web Dev Simplified

Kyle's YouTube Channel - Web Dev Simplified

Final Thoughts

That's it for now. I hope you got to learn something new and enjoyed reading my blog. Will meet you next time with a new blog on a new React hook. Till then buh-bye and stay safe, stay happy, and code furiously!!!!

Oh... I almost forgot!! Happy Valentine's day!!!!

You can follow me on Github, LinkedIn.