February 14, 2024 - Edited on February 16, 2024
The useEffect hook in React is used for side effects in functional components.
Here's the basic syntax:
useEffect(() => { // Side effect code goes here }, [dependencies]); // This code will run each time the dependencies change
Let's break down the components of this syntax:
useEffect
: This is the hook provided by React to perform side effects in functional components.() => { /* Side effect code */ }
: This is the function that contains the code for the side effect. It will run after the component renders. The function can return a cleanup function (optional), which will be executed before the component unmounts or before the next useEffect execution.[dependencies]
: This is an optional array of dependencies. If provided, the effect will only re-run if any of the dependencies have changed between renders. If no dependencies are provided ([]
), the effect will only run once.
This can be used to cover many use cases.
Example 1: loading data from a server
Checkout this simple example where you can see a GitHub users details:
👇Enter your Github handle
Loading...
import React, { useState, useEffect } from "react";
const GithubProfile = ({ username }) => {
const [profileData, setProfileData] = useState(null);
useEffect(() => {
const fetchProfile = async () => {
try {
const response = await fetch(`https://api.github.com/users/${username}`);
const data = await response.json();
setProfileData(data);
} catch (error) {
console.error("Error fetching GitHub profile:", error);
}
};
fetchProfile();
// depends on username.
// the effect will run each time it changes
}, [username]);
return (
<div>
{profileData ? (
<div>
<h2>{profileData.login}</h2>
<img src={profileData.avatar_url} alt={`${profileData.login}'s avatar`} />
<p>{profileData.bio}</p>
</div>
) : (
<p>Loading...</p>
)}
</div>
);
};
export default GithubProfile;
It can be used Like follows in your app:
import React ,{ useState }from "react"; import GithubProfile from "./GithubProfile"; const App = () => { const [userName,setUserName]=useState("youssefbenlemlih"); return ( <div> <h1>GitHub Profile Viewer</h1> <input type={"text"} value={userName} onChange={(e) => setUserName(e.target.value)} /> <GithubProfile username={userName} /> </div> ); }; export default App;
Now each time the user name changes, the effect function will be called and the new information will be shown.
import React, { useState, useEffect } from 'react'; const ShowWindowWidth = () => { const [width, setWidth] = useState(window.innerWidth); useEffect(() => { const handleResize = () => { setWidth(window.innerWidth); }; // Add event listener when the component mounts window.addEventListener('resize', handleResize); // Cleanup function to remove the event listener when the component unmounts return () => { window.removeEventListener('resize', handleResize); }; }, []); // The empty dependency array ensures that this effect runs only once, similar to componentDidMount return ( <div> <p>Window Width: {width}</p> </div> ); }; export default ShowWindowWidth;
Explain
Attention: in dev mode in react strict mode, react will run your effect and cleanup twice, to make it obvious when you don’t provide a correct cleanup function (link external blog of tweet)