visit
React's useEffect
hook is one of the trickiest and most powerful hooks in functional components, as it allows you to perform side effects in react. But what is a side effect? In React, a ‘side effect’ is any operation that affects something outside of the component such as making a REST API call, updating the DOM, etc. It will run after the component is rendered. If you are familiar with class-based components, then the useEffect hook can be easily understood as a combination of the lifecycle methods componentDidMount, componentDidUpdate, and componentWillUnmount.
The useEffect hook should be used anytime you need your functional component to perform a side effect. This can include things like fetching data, setting up subscriptions, and updating the DOM. It is important to note that the useEffect hook should not be used for rendering purposes, as it is not designed to replace React's rendering mechanism.
Some of the scenarios where the useEffect hook can come in handy include:
useEffect(() => {
// function body
}, [dependencies]);
The useEffect
hook is called within a functional component and it takes two arguments: a function that represents the effect body and an optional array of dependencies. The effect function is executed after the component has been rendered. When the dependencies array is specified, and the values of the arguments in the dependencies array are changed, it will trigger to re-run the effect.
useEffect(() => {
// effect function
return () => {
// cleanup function
};
}, [dependencies]);
The effect function can return a cleanup
function that will be run before the effect is run again or before the component unmounts. This cleanup function can be used to perform any necessary cleanup operations, such as canceling network requests or removing event listeners or unsubscribing from data sources, etc.,
There can be more than one useEffect in the same functional component.
To use the useEffect hook, you will first need to import it from the react
library. Then, you can call the useEffect function within your component, and pass in a function that represents the effect you want performed.
import { useEffect } from "react";
function MyComponent() {
useEffect(() => {
// Your effect function here
}, []);
return <div>Hello World</div>;
}
import { useEffect } from "react";
function MyComponent() {
useEffect(() => {
console.log("This will be run every time the component renders");
});
return <div>Hello World</div>;
}
import { useEffect, useState } from "react";
function Posts() {
const [posts, setposts] = useState([]);
useEffect(() => {
fetch("//jsonplaceholder.typicode.com/users/1/posts")
.then((resp) => resp.json())
.then((blogPosts) => setposts(blogPosts));
}, []);
return (
<div className="App">
{posts && posts.map((post) => <li>{post.title}</li>)}
</div>
);
}
export default Posts;
import { useEffect, useState } from "react";
function Search() {
const [posts, setposts] = useState([]);
const [search, setsearch] = useState("");
useEffect(() => {
const filteredPosts = posts.filter((p) => p.title.includes(search));
setposts(filteredPosts);
}, [search]);
return (
<div className="App">
{posts && (
<input
type="text"
value={search}
onChange={(e) => setsearch(e.target.value)}
/>
)}
{posts && posts.map((post) => <li>{post.title}</li>)}
</div>
);
}
export default Search;
So, whenever the user enters a search term, the search
state changes and causes the effect to re-run.
import { useEffect, useRef, useState } from "react";
function Dropdown() {
const ref = useRef(null);
const [open, setOpen] = useState(false);
const [options, setoptions] = useState([
{ key: 1, value: "Audi" },
{ key: 2, value: "BMW" },
{ key: 3, value: "Jaguar" },
{ key: 4, value: "Ferrari" }
]);
const [option, setOption] = useState("");
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(false);
}
};
document.addEventListener("click", handleClickOutside);
return () => document.removeEventListener("click", handleClickOutside);
}, []);
return (
<div ref={ref}>
<button onClick={() => setOpen(!open)}>Toggle Dropdown</button>
{open && (
<ul>
{options.map((option) => (
<li key={option.key} onClick={() => setOption(option.value)}>
{option.value}
</li>
))}
</ul>
)}
</div>
);
}
export default Dropdown;
import { useEffect, useState } from "react";
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1);
});
return <div>{count}</div>;
}
import { useEffect, useState } from "react";
function Posts() {
const [posts, setposts] = useState([]);
useEffect(() => {
fetch("//jsonplaceholder.typicode.com/users/1/posts")
.then((resp) => resp.json())
.then((blogPosts) => setposts(blogPosts));
});
return (
<div className="App">
{posts && posts.map((post) => <li>{post.title}</li>)}
</div>
);
}
export default Posts;
import { useEffect } from "react";
function TodoList({ todos, filter }) {
useEffect(() => {
console.log("filtering todos");
// filter todos
}, [todos, filter]);
return <div>{/* todo list JSX */}</div>;
}
import { useEffect, useRef, useState } from "react";
function Dropdown() {
const ref = useRef(null);
const [open, setOpen] = useState(false);
const [options, setoptions] = useState([
{ key: 1, value: "Audi" },
{ key: 2, value: "BMW" },
{ key: 3, value: "Jaguar" },
{ key: 4, value: "Ferrari" }
]);
const [option, setOption] = useState("");
useEffect(() => {
const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setOpen(false);
}
};
document.addEventListener("click", handleClickOutside);
// No Cleanup function
}, []);
return (
<div ref={ref}>
<button onClick={() => setOpen(!open)}>Toggle Dropdown</button>
{open && (
<ul>
{options.map((option) => (
<li key={option.key} onClick={() => setOption(option.value)}>
{option.value}
</li>
))}
</ul>
)}
</div>
);
}
export default Dropdown;