In React, a component's lifecycle refers to the different stages it goes through from the moment it is created (mounted) to the moment it is destroyed (unmounted).
Let’s understand each stage in detail.
1. Mounting
This is when a component is created and added (rendered) to the DOM. During this stage, the component's constructor, render method, and any initial side effects (like useEffect) will run.
Common states in mounting
1. The component's initial state is set (e.g., useState).
2. The useEffect hook (with an empty dependency array []) runs after the component renders for the first time.
2. Updating
Once the component is mounted, it can update due to changes in its props or state. React re-renders the component when necessary and trigger the updates.
Common states in updating
1. When a component's props or state changes, the render method is called again.
2. If the component has a useEffect with dependencies, it will re-run the effect when the specified dependencies change.
3. This is the phase where React compares the Virtual DOM with the real DOM to update the UI efficiently.
3. Unmounting
Unmounting is the process where a component is removed from the DOM. This can happen for several reasons, such as:
1. Navigation to a different route.
2. The parent component no longer renders the child component.
3. Conditional rendering based on state.
When a component is unmounted
1. The component is completely removed from the DOM.
2. This is where the cleanup function from useEffect comes into play. Before the component is removed, any ongoing effects (like event listeners, subscriptions, or timers) should be cleaned up to prevent memory leaks or errors. This cleanup function will be executed when the component unmounts or before the effect re-runs.
Example
<!-- HTML generated using hilite.me --><div style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;"><pre style="margin: 0; line-height: 125%"><span style="color: #008800; font-weight: bold">import</span> React, { useState, useEffect } from <span style="background-color: #fff0f0">"react"</span>;
<span style="color: #008800; font-weight: bold">const</span> WindowSizeTracker <span style="color: #333333">=</span> () <span style="color: #333333">=></span> {
<span style="color: #008800; font-weight: bold">const</span> [windowWidth, setWindowWidth] <span style="color: #333333">=</span> useState(<span style="color: #007020">window</span>.innerWidth);
<span style="color: #888888">// Effect to handle window resize event</span>
useEffect(() <span style="color: #333333">=></span> {
console.log(<span style="background-color: #fff0f0">"Component mounted"</span>);
<span style="color: #008800; font-weight: bold">const</span> handleResize <span style="color: #333333">=</span> () <span style="color: #333333">=></span> {
setWindowWidth(<span style="color: #007020">window</span>.innerWidth);
};
<span style="color: #888888">// Add event listener on component mount</span>
<span style="color: #007020">window</span>.addEventListener(<span style="background-color: #fff0f0">"resize"</span>, handleResize);
<span style="color: #888888">// Cleanup function to remove event listener on unmount</span>
<span style="color: #008800; font-weight: bold">return</span> () <span style="color: #333333">=></span> {
console.log(<span style="background-color: #fff0f0">"Component unmounted, un-registering resize event"</span>);
<span style="color: #007020">window</span>.removeEventListener(<span style="background-color: #fff0f0">"resize"</span>, handleResize);
};
}, []); <span style="color: #888888">// Empty array ensures this effect runs only once</span>
<span style="color: #008800; font-weight: bold">return</span> (
<span style="color: #333333"><</span>div<span style="color: #333333">></span>
<span style="color: #333333"><</span>h1<span style="color: #333333">></span>Window Width<span style="color: #333333">:</span> {windowWidth}<span style="color: #333333"><</span><span style="color: #FF0000; background-color: #FFAAAA">/h1></span>
<span style="color: #333333"><</span><span style="color: #FF0000; background-color: #FFAAAA">/div></span>
);
};
</pre></div>
In the provided snippet, the cleanup of resources is handled through the useEffect hook, specifically using the return function.
When the component mounts, an event listener for the window's resize event is added using window.addEventListener("resize", handleResize);. This listener updates the component's state (windowWidth) whenever the window is resized.
Cleanup Function
The useEffect hook returns a cleanup function (return () => { ... };), which is called when the component unmounts or before the effect runs again (if dependencies change). In this case, the cleanup function logs a message indicating that the component is being unmounted and un-registers the resize event listener with window.removeEventListener("resize", handleResize);.
Why Cleanup is Important?
1. Prevents Memory Leaks: By removing the event listener when the component is unmounted, you prevent potential memory leaks that could occur if the listener were to remain active.
2. Avoids Performance Issues: Without cleanup, if the component is toggled on and off repeatedly, multiple event listeners could stack up, leading to performance degradation.
Let us try to understand this with a detailed example.
Step 1: Go to the post (Quickly Set Up a React Project with Vite: A Step-by-Step), and set up a React Project ‘cleanup-using-use-effect-hook’
Project structure looks like below.
Step 2: Create components folder in src/ folder and define window size tracker component.
WindowSizeTracker.jsx
import React, { useState, useEffect } from "react";
const WindowSizeTracker = () => {
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
// Effect to handle window resize event
useEffect(() => {
console.log("Component mounted");
const handleResize = () => {
setWindowWidth(window.innerWidth);
};
// Add event listener on component mount
window.addEventListener("resize", handleResize);
// Cleanup function to remove event listener on unmount
return () => {
console.log("Component unmounted, un-registering resize event");
window.removeEventListener("resize", handleResize);
};
}, []); // Empty array ensures this effect runs only once
return (
<div>
<h1>Window Width: {windowWidth}</h1>
</div>
);
};
export default WindowSizeTracker;
Step 3: Update App.jsx file like below.
App.jsx
import React, { useState } from "react";
import WindowSizeTracker from "./components/WindowSizeTracker";
const App = () => {
const [showComponent, setShowComponent] = useState(true);
return (
<div>
<button onClick={() => setShowComponent(!showComponent)}>
{showComponent ? "Hide Component" : "Show Component"}
</button>
{showComponent && <WindowSizeTracker />}
</div>
);
};
export default App;
Step 4: Update main.jsx file like below.
main.jsx
import { createRoot } from "react-dom/client";
import App from "./App.jsx";
createRoot(document.getElementById("root")).render(<App />);
Step 5: Follow below steps to build and run the Application.
cd cleanup-using-use-effect-hook npm install npm run dev
You can download this application from this link.
Previous Next Home
No comments:
Post a Comment