In this article, we will learn about the differences between useEffect and useLayoutEffect in React with the help of an example. We will create a counter and implement it using both useEffect and useLayoutEffect to understand the differences practically.
useEffect
The useEffect is used to perform side effects in function components. This includes data fetching, subscriptions, manually changing the DOM, and others.
The useEffect hook takes two arguments:
- A callback function that contains the side effect code.
- An optional array of dependencies. The callback function will only be called when any of the dependencies change.
Syntax
useEffect(() => {
// Side effect function
}, [dependencies]);
Advantages
- useEffect can be used to fetch data from an API on the initial render or when a dependency changes. This can help you to keep your components up-to-date with the latest data.
- useEffect can help to improve the performance of your application by intelligently optimizing the execution of side effects.
Disadvantages
- useEffect can be used to do almost anything, but it is important to use it sparingly. If you overuse useEffect, your components can become complex and difficult to maintain.
- Performance optimizations like skipping effects on certain renders are not built-in and require manual bookkeeping with flags/states.
Example: We use the useEffect hook to perform a side effect. In this case, we update the document title to display the current count value. We also provide an optional array of dependencies [count], which specifies that this effect should run whenever the count state variable changes.
Javascript
// App.js import React, { useState, useEffect, } from "react" ; import "./App.css" ; function App() { const [count, setCount] = useState(0); useEffect(() => { document.title = `Count: ${count}`; // This function will be called when the // component unmounts or when the count changes return () => { document.title = "React App" ; }; }, [count]); // Function to increment the count const incrementCount = () => { setCount(count + 1); }; return ( <div className= "App" > <h1>neveropen</h1> <h2>useEffect Example</h2> <h2>Count: {count}</h2> <button onClick={incrementCount}> Increment </button> </div> ); } export default App; |
CSS
h 1 { color : green ; } button { background-color : green ; color : white ; padding : 10px 20px 10px 20px ; text-align : center ; border-radius: 5px ; } |
Output:
useLayoutEffect
The useLayoutEffect hook is a React hook that allows you to perform side effects that affect the layout of your component. Side effects are any changes that your component makes to the outside world, such as fetching data, updating the DOM, or subscribing to an event.
The useLayoutEffect hook takes two arguments:
- A function that contains the effect you want to run.
- An optional array of dependencies. The callback function will only be called when any of the dependencies change.
Syntax
useLayoutEffect(() => {
// runs synchronously after commit
return () => {
// cleanup
}
}, [input])
Advantages
- useLayoutEffect gives you more control over the layout of your component. This can be useful for implementing complex animations or transitions.
- It allows synchronizing with the browser layout before paint. This is useful for measuring DOM nodes/sizes or integrating with non-React DOM libraries.
Disadvantages
- useLayoutEffect is synchronous, meaning that it blocks the browser from painting the DOM until it has finished executing. This can lead to performance problems if you use it too often or for expensive operations
- Debugging is harder since it runs synchronously before paint. Issues may not be obvious if they occur before visual updates.
Example: We use useLayoutEffect to add an effect that runs synchronously after each render of the component. Inside this effect, we update the count state by incrementing it by 1 whenever the count state itself changes. This creates a loop that continually increments the count after each render.
Javascript
//app.js import React, { useState, useLayoutEffect, } from "react" ; import "./App.css" ; function App() { const [count, setCount] = useState(0); useLayoutEffect(() => { console.log( "useLayoutEffect - Component did update" ); document.title = `Count: ${count}`; }, [count]); return ( <div className= "App" > <h1>neveropen</h1> <h2> useLayoutEffect Example </h2> <p>Count: {count}</p> <button onClick={() => setCount(count + 1) }> Increment </button> </div> ); } export default App; |
CSS
h 1 { color : green ; } button { background-color : green ; color : white ; padding : 10px 20px 10px 20px ; text-align : center ; border-radius: 5px ; } |
Output:
Difference between useEffect and useLayoutEffect
Feature |
useEffect |
useLayoutEffect |
---|---|---|
Execution |
Runs after component render and DOM update. |
Runs synchronously after render but before DOM update. |
Dependencies Array |
Optional; allows specifying dependencies to control when the effect runs. |
Optional; also accepts a dependencies array, but its behavior is more synchronous. |
Can be used to |
Perform side effects, such as fetching data, making API calls, or updating the DOM. |
Perform side effects that are related to the layout of the component, such as setting the position or size of an element. |
Cleanup Function |
Supports cleanup function for unmount and dependency changes |
Supports cleanup function for unmount and dependency changes |
Can cause performance problems |
Yes, if it is used to perform side effects that do not need to be executed synchronously. |
No, because it is executed synchronously. |