React is a popular JavaScript library used for building user interfaces. One of the most important aspects of building robust React applications is managing state and handling side effects. This is where the React useEffect hook comes in. In this article, we will explore the React useEffect hook in detail and provide examples of where and how it can be used.
What is useEffect?
The useEffect hook is a built-in React hook that allows us to handle side effects in functional components. Side effects are actions that are not directly related to rendering components, such as fetching data from an API, setting timers, or manipulating the DOM.
The useEffect hook is called after every render of the component. It takes a callback function as an argument, which is called after the component is mounted and after every update. The hook also accepts a second argument, which is an array of dependencies that determine when the effect should be called.
Basic Usage
Let’s start with a simple example. Consider a component that fetches data from an API and displays it on the screen. We can use the useEffect hook to fetch the data and update the component when the data changes.
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [data, setData] = useState([]);
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos');
const json = await response.json();
setData(json);
};
fetchData();
}, []);
return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
In the above example, we declare a state variable called data using the useState hook. We use the useEffect hook to fetch data from the API and update the data state when the component mounts. We pass an empty array as the second argument to useEffect, which means that the effect should only be called once, when the component mounts.
Conditional Effects
Sometimes we want to call an effect only when a specific value changes. We can achieve this by passing the value as a dependency in the second argument of the useEffect hook. For example, consider a component that displays the current time and updates it every second.
import React, { useState, useEffect } from 'react';
function Clock() {
const [time, setTime] = useState(new Date());
useEffect(() => {
const timer = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(timer);
}, []);
return (
<div>
<h1>Current Time: {time.toLocaleTimeString()}</h1>
</div>
);
}
In the above example, we declare a state variable called time using the useState hook. We use the useEffect hook to set up a timer that updates the time state every second. Then we pass an empty array as the second argument to useEffect, which means that the effect should only be called once, when the component mounts. We also return a cleanup function that clears the timer when the component unmounts.
Cleanup Effects
When using effects, it is important to clean up after ourselves to prevent memory leaks. We can achieve this by returning a cleanup function from the effect. For example, consider a component that sets the document title.
import React, { useEffect } from 'react';
function DocumentTitle({ title }) {
useEffect(() => {
document.title = title;
return () => {
document.title = '';
};
}, [title]);
return null;
}
In the example above, we declare a component called DocumentTitle
that sets the document title based on the title
prop. We use the useEffect
hook to set the document title and return a cleanup function that resets it to an empty string.
The useEffect
hook can also be used to fetch data from an API when a component mounts. For example, consider a component that displays a list of posts fetched from an API.
import React, { useState, useEffect } from 'react';
function PostList() {
const [posts, setPosts] = useState([]);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => setPosts(data));
}, []);
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}
In the example above, we declare a component called PostList
that fetches posts from an API using the useEffect
hook. We declare a state variable called posts
to store the fetched data and use the setPosts
function to update the state when the data is fetched.
The second argument to the useEffect
hook is an array of dependencies that determine when the effect should run. In the example above, we pass an empty array to indicate that the effect should only run once when the component mounts.
Conclusion
In conclusion, the useEffect
hook is a powerful tool that allows us to perform side effects in our React components. It can be used to update the document title, fetch data from an API, or perform any other side effect necessary for our application. Just be sure to clean up after yourself to prevent memory leaks!