React is a popular frontend UI library that is used in almost 50 million projects each month. React, which is supported by Facebook, has a long history of dominance in the web development industry and a long list of notable clients, including Fortune 500 firms and both startups and established businesses.
React utterly depends on components, which are the basic building blocks of React applications. There are two approaches to writing a React component in the world of React. The first employs a functional approach, whereas the second employs a class-based approach. These days, functional components are quite popular, and the introduction of hooks has encouraged more people to adopt creating function-based components.
Some of the most useful hooks available are useState, useEffect, useRef, useLayoutEffect, useMemo, etc. In this in-depth article, we will cover the difference between the useEffect and useLayoutEffect hooks.
What is the useEffect hook in React?
Eliminating the side effects of using class-based components is the driving force behind the development of useEffect Hook. One thing to keep in mind is that useEffect only runs after React renders your component, so your effect callback will not prevent browser painting. This is different from how class components behave, where componentDidUpdate and componentDidMount run synchronously following the rendering. This approach is more efficient, which is generally what you want most of the time.
For instance, actions like updating the DOM, obtaining data from API endpoints, configuring timers or subscriptions, etc., may have unintended side effects.
The following situations in functional components allow for the use of the useEffect hook to carry out operations (or side effects):
- when a component is rendered (componentDidMount function in class-based components).
- when a component undergoes an update (componentDidUpdate function in class-based components).
- before a component is unmounted or removed (componentWillUnmount function in class-based components).
Most frequently, we use useEffect hooks to carry out actions such as obtaining data from an API, altering the DOM, or performing a specific method when the useEffect’s dependency changes.
How to write useEffect hooks in React
Every time the useEffect hook is activated, it returns a callback function that will execute the declared function. The dependency array decides when the useEffect should be triggered. If we have an empty dependency array, the useEffect will only work once when the component renders. If we have single or multiple dependencies, useEffect will be triggered whenever the dependencies undergo a change.
Let’s examine a straightforward example of useEffect in action.
The output will be the following:
You can see that when the component renders, the useEffect hooks are only executed once. However, if there is another change in the DOM, it will cause the useEffect to be triggered for the second time. To avoid this, pass an empty dependency array.
Now that we have a good idea about how the effect works, let’s discuss the useLayoutEffect hook in React.
What is useLayoutEffect hook in React?
React’s useLayoutEffect hook is almost identical to the useEffect hook. A function called effect and an array of dependencies are the first and second arguments, respectively, for the useLayoutEffect hook.
After all DOM mutations have been completed by React, useLayoutEffect executes synchronously. If you need to measure the DOM (for example, to determine the scroll position or other styles for an element) and then modify the DOM or cause a synchronous re-render by changing the state, this can be helpful.
The useLayoutEffect hook’s syntax is almost identical to that of the useEffect hook. The effect, the first argument, has two possible outcomes: cleanup function or undefined. The code below demonstrates the useLayoutEffect function.
As you can see from the function above, useEffect and useLayoutEffect both accept an array of dependencies and an effect function as arguments, and they return either undefined or a cleanup function.
Let’s examine a sample of how to use the useLayoutEffect hook.
The output of the following will be:
It is noticeable that useLayoutEffect functions in a manner identical to that of the useEffect hook. So what is the actual difference between these two hooks?
What is the difference between useLayoutEffect and useEffect hook?
The main difference between the useEffect hook and the useLayoutEffect hook is that the useEffect hook serves asynchronously, whereas the useLayoutEffect hook works synchronously. In simple words, we can say that the difference between useEffect and useLayoutEffect is in the time at which these functions are invoked.
It is useful to be aware of the steps that component re-render takes in order to comprehend when the hooks are called. Assuming that the useEffect hook is active in our app, we can get this series of events to happen.
- The user engages with the React app. Let’s just say the user clicks a button on the UI.
- The state of the components changes.
- The DOM is then mutated.
- Changes are then reflected on the browser screen.
- The function is invoked to clean up effects from the previous render if useEffect dependencies have changed.
- Following cleanup, the useEffect hook is invoked.
For the useLayoutEffect hook, the series of events will be
- The user interacts with the app. Let’s just say the user clicks a button on the UI.
- The state of the components changes.
- The DOM is then mutated.
- The function is invoked to clean up effects from the previous render if useLayoutEffect dependencies have changed.
- Following cleanup, the useLayoutEffect hook is invoked.
- The browser screen updates to reflect changes.
Your effect will typically involve synchronizing some state or props with something that doesn’t need to happen instantly or that doesn’t visually change the page. We might only need to retrieve data from an API, set an event handler, or take action when the state changes. The useEffect hook is employed to accomplish these kinds of tasks.
When to use useLayoutEffect hook in React
The useLayoutEffect hook should be used when your component flickers when the state is updated, which means that it first renders in a partially-ready state before re-rendering in its final state right away.
Now let’s compare useLayoutEffect and useEffect using an example:
We developed a simple app with a button element. When the user clicks the button, the value is updated to 0 and the dependency array of the useLayoutEffect array is value. Within the useLayoutEffect, we check the value and if it is 0, it changes the value from 0 to a random number.
In this example, the component is rendered twice, but the value is only updated once in the browser. Let’s look at the same example with useLayoutEffect.
You can see there is flickering when using useEffect since the component is rendered twice and the value is also updated twice.
Even though the component renders twice, the version with useLayoutEffect only updates visually once. On the other hand, the useEffect version renders twice, resulting in a blip where the value is briefly 0.
The main difference between the useEffect and useLayoutEffect hooks, as shown in the example, is the time at which they are fired. We will look into some real-world applications of these two hooks with some examples.
Let’s create an app that fetches data from a dummy backend API.
The output of the following code will be:
If you run this example on your machine, you will see that data is populated first in useLayoutEffect and then in useEffect. This is just because of the synchronous nature of the useLayoutEffect hook and the asynchronous nature of the useEffect hook.
UseLayoutEffect is preferred over useEffect hooks in the following situations:
Unforeseen visual or state changes
When dealing with inconsistent visual changes, the useLayoutEffect truly shines. When you use useEffect, you’ll notice a flicker before the DOM changes are painted, which is caused by how refs are passed on to custom hooks. These refs are initially null before being set when the attached DOM node is rendered.
When the effect does not require heavy computations
Both useEffect and useLayoutEffect behave differently in terms of how heavy computations are handled. As previously stated, useEffect will postpone the execution of the effect function until after the DOM mutations have been painted, making it the obvious choice of the two.
When we do heavy computation inside useLayoutEffect, we will block the DOM to re-render for some time. 99% of the time, we don’t need to block DOM updates. At this point in time, we only need to use useEffect and not useLayoutEffect.
Which is preferred, useEffect or useLayoutEffect?
The majority of the time, useEffect is the best option. If your code is causing flickering, try using useLayoutEffect instead and see if that tends to help.
Because useLayoutEffect is synchronous, the application will not update visually until your effect has finished running. If you have slow code in your effect, it may cause performance issues such as stuttering. Because most effects do not require breaking the default flow while they run, regular useEffect is always the best option in almost all cases, except a few.
Congratulations on reaching this far! You’re a fantastic reader!!
In this detailed blog on useEffect v/s useLayoutEffect, we have seen various similarities as well as the uniqueness of useEffect and useLayoutEffect hooks. Not only did we understand the theory, but we also got our hands dirty by going through several real-world examples.
Now you know when to use useEffect and useLayoutEffect efficiently.