React Hooks: useEffect
Welcome to the another article in the React Hooks series, where the magic of managing side effects unfolds! If React components are the building blocks of your web applications, then useEffect
is the dynamic glue that connects them to the wider world.
In the ever-evolving landscape of web development, harnessing the power of side effects is essential for creating robust and interactive user interfaces. Imagine a world where your components seamlessly sync with external data sources, respond to user interactions, and gracefully handle the ebb and flow of the application lifecycle. This is precisely where useEffect
steps into the spotlight.
Let’s dive in and discover the captivating world of useEffect
—where React components come to life. 🚀✨
Introduction
useEffect
is a React Hook that lets you perform side effects in your components, such as data fetching, subscriptions, manual DOM manipulations, or any other operations that need to take place after the component has been rendered.
A useEffect
hook takes in two arguments:
setup: this is a function that contains your useEffect
’s logic. This function is the side effect you want to perform. It runs after the component has been rendered. This can include data fetching, setting up subscriptions, or any code that needs to run after the component is displayed. You can also define an optional cleanup function in this logic that React will run after your component has been removed from the DOM. React will also first run the cleanup function with the old values before running the setup function with the new values when a re-render is triggered by changed dependencies.
dependency array (optional): an array of reactive values e.g. state, props, functions and variables declared inside your component that your setup function is dependent on to run. If any of the dependencies change between renders, the effect function will run again. If the dependencies array is empty, the effect will run only once after the initial render.
cleanup function (optional): If your effect has cleanup requirements (e.g., unsubscribing from a subscription), you can return a function from the useEffect
. This function will be called before the component is unmounted, and also before the next effect run if the dependencies change.
useEffect(setup, dependencies);
Effects are typically used to “step out” of your React code and synchronize with some external system. This includes browser APIs, third-party widgets, network, and so on. Here are some situations where you might not need an Effect.
An example
In this example, the external system we would be trying to synchronize with is the browser API. We want to monitor an event, window resizing, in the global window object.
import React, { useState, useEffect } from "react";
export default function ResizeListener() {
// State to store the window dimensions
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
// useEffect to add event listener for window resize
useEffect(() => {
// Event handler function to update windowSize state
const handleResize = () => {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
};
// Add event listener on component mount
window.addEventListener("resize", handleResize);
// Cleanup function to remove event listener on component unmount
return () => {
window.removeEventListener("resize", handleResize);
};
}, []); // Empty dependency array for running the effect only once after the initial render
return (
<div>
<p>Window Width: {windowSize.width}</p>
<p>Window Height: {windowSize.height}</p>
{windowSize.width < 768 ? <p>Mobile</p> : <p>Desktop</p>}
</div>
);
}
In the component above, useEffect
lets us connect to the window
object and listen to its resize event. This effect lets us add an event listener to our window object when the component mounts, set the window size for display in our UI, and then remove our event listener in a cleanup function, after our component unmounts.
Usage
Here are some common use cases of the useEffect
hook:
- Component Lifecycle Operations:
useEffect(() => {
// Code to run after each render
return () => {
// Code to run before the component is unmounted
};
}, [/* dependencies */]);
2. Subscription Management
useEffect(() => {
// Subscribe to a data stream or WebSocket
const subscription = subscribeToData(data => {
// Handle incoming data
setData(data);
});
// Cleanup: Unsubscribe when component is unmounted
return () => {
subscription.unsubscribe();
};
}, [/* dependencies */]);
3. DOM Manipulation:
useEffect(() => {
// Manipulate the DOM after component renders
document.title = `New Title`;
// Cleanup: Revert changes when component is unmounted
return () => {
document.title = `Original Title`;
};
}, [/* dependencies */]);
4. Data Fetching:
useEffect(() => {
const fetchData = async () => {
// Fetch data from an API
const response = await fetch('https://api.example.com/data');
const result = await response.json();
// Update state with fetched data
setData(result);
};
fetchData();
// cleanup function would abort the network request if dependency changes or ignore its result
// learn more https://developer.mozilla.org/en-US/docs/Web/API/AbortController
}, [/* dependencies */]);
5. Event Listeners:
useEffect(() => {
const handleClick = () => {
// Handle click event
};
// Add event listener on mount
document.addEventListener('click', handleClick);
// Cleanup: Remove event listener on unmount
return () => {
document.removeEventListener('click', handleClick);
};
}, [/* dependencies */]);
6. Interval or Timeout Operations:
useEffect(() => {
const intervalId = setInterval(() => {
// Code to run at intervals
}, 1000);
// Cleanup: Clear interval on unmount
return () => {
clearInterval(intervalId);
};
}, [/* dependencies */]);
7. Dependency-based Operations:
useEffect(() => {
// Code to run when dependencies change
}, [dependency1, dependency2]);
8. Document Title Updates:
useEffect(() => {
document.title = 'New Page Title';
}, [/* dependencies */]);
9. Animation Effects:
useEffect(() => {
// Trigger animations or transitions after render
// or connect to a 3rd party animation library and start animation on mounted DOM node
// Cleanup: stop animation on unmount
return () => {
};
}, [/* dependencies */]);
Recap
useEffect
provides a flexible way to handle side effects in React components. The key is to use it for operations that involve interactions with external systems, subscriptions, or anything that goes beyond the normal rendering of the component. I hope you learned something and now understand the useEffect
hook and how to use it in your application.
Please leave a like if this was helpful. Comment also if you have questions.
Happy Coding🙌