Mahamudul Hasan Rubel
HomeAboutProjectsSkillsExperienceBlogPhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • About
  • Projects
  • Skills
  • Experience
  • Blog
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
ReactNext.jsJune 21, 20264 min read

React lifecycle: Mastering Mounting, Updating, and Unmounting

Master the React lifecycle to write predictable code. Learn how to handle component mounting, updating, and unmounting to avoid common memory leaks.

ReactFrontend DevelopmentJavaScriptWeb PerformanceHooksNext.jsTutorial

When I started with React back in 2017, I spent way too much time fighting the "lifecycle methods." I remember staring at componentDidMount and componentWillUnmount, trying to figure out why my data was fetching twice or why my event listeners were leaking memory like a sieve. If you're feeling that same frustration, don't worry—it’s just a symptom of a missing mental model.

Modern React doesn't use those class-based methods anymore, but the React lifecycle concepts remain exactly the same. Whether you’re using functional components or hooks, every component goes through three main phases: it appears, it changes, and it disappears.

The Three Phases of the React Lifecycle

Think of a component’s life as a journey. It’s born (mounting), it evolves (updating), and eventually, it’s removed from the screen (unmounting).

If you've already explored useState and useEffect: A Mental Model for React Beginners, you know that useEffect is the primary tool for managing these stages. Let’s break them down.

1. Mounting (The Birth)

This happens when your component is first inserted into the DOM. React runs your function, calculates the JSX, and paints it to the screen. If you have any useEffect hooks with an empty dependency array ([]), they trigger right after this first render.

We used to use this phase to fire off API calls. While that’s still common, keep in mind that React Rendering: How State Updates and Reconciliation Work means your component might run its logic more than once during development due to Strict Mode. Always design your effects to be idempotent.

2. Updating (The Evolution)

Components update when their state or props change. React compares the new JSX with the old one, figures out what actually changed, and updates the DOM.

This is where beginners often get stuck. You might be triggering an update every time a user types in an input, causing a heavy function to run on every keystroke. If you notice your app feeling sluggish, it’s usually because you’ve missed a detail in the React Rendering Lifecycle: Why Components Re-render and How to Optimize. Understanding that every state change is a re-render is the first step toward fixing performance issues.

3. Component Unmounting (The Goodbye)

This is the phase most juniors overlook. Component unmounting occurs when a component is removed from the UI—like when a user navigates away or a conditional render hides it.

If you attached a global event listener (like window.addEventListener) or started a timer (setInterval) inside an effect, you must clean it up. If you don't, that code keeps running in the background, consuming memory and causing bugs that are a nightmare to debug.

Using React useEffect Cleanup Effectively

The secret to handling the end of a component's life is the useEffect cleanup function. If you return a function from your useEffect, React calls that function right before the component unmounts.

Here is a common scenario I see when mentoring juniors:

JAVASCRIPT
useEffect(() => {
  const handleResize = () => console.log(window.innerWidth);
  window.addEventListener(CE9178">'resize', handleResize);

  // This is the cleanup function
  return () => {
    window.removeEventListener(CE9178">'resize', handleResize);
  };
}, []); // Empty array means this only runs once

If you omit that return block, every time your component mounts, you add another listener to the window object. After ten navigation cycles, you'll have ten listeners doing the same thing. That’s a memory leak.

Why My First Attempt Failed

Early in my career, I tried to handle a WebSocket connection by just opening it inside the component body. It broke immediately. Every time the component re-rendered, it opened a new socket connection, eventually crashing the browser tab.

I realized I needed to treat the connection as a lifecycle event. I moved the logic into useEffect, and more importantly, I used the cleanup function to close the socket. Always assume your component will be destroyed and recreated; if your code isn't prepared for that, it’s not production-ready.

FAQ: Common Lifecycle Questions

Q: Does every re-render trigger useEffect? A: No. useEffect only runs if you provide a dependency array and one of those values changes. If you leave the array out entirely, it runs after every single render, which is almost always a mistake.

Q: Is "mounting" the same as "rendering"? A: Not quite. Rendering is the process of React calling your function to see what the UI should look like. Mounting is the specific moment that UI is actually committed to the browser DOM.

Q: How do I know when to use the cleanup function? A: Ask yourself: "If this component disappears, does this side effect need to stop?" If you set a timer, fetch data that is no longer needed, or add a listener to the global window object, you need a cleanup function.

Moving Forward

The React lifecycle isn't something you memorize; it's something you observe. Start by adding console.log statements at the top of your components and inside your useEffect blocks to see exactly when they fire. You'll quickly see the pattern of mounting and updating.

Next time you're stuck, stop and ask: "Is my component mounting again, or is it just updating?" That one question usually saves me about thirty minutes of debugging. Don't worry if it still feels like magic; even after years of doing this, I still find myself double-checking the dependency arrays in my effects.

Back to Blog

Similar Posts

ReactNext.jsJune 21, 20264 min read

React State Synchronization: How to Avoid Infinite Loops

Master React state synchronization by avoiding unnecessary useEffect calls. Learn to handle dependent inputs correctly and keep your components predictable.

Read more
Close-up of JavaScript code on a laptop screen, showcasing programming in progress.
React
Next.js
June 20, 2026
4 min read

Fetching data in a React component the right way

Fetching data in a React component the right way isn't just about calling an API. Avoid common useEffect traps and build faster, more stable apps today.

Read more
ReactNext.jsJune 21, 20265 min read

React Conditional Rendering: Mastering Guard Clauses and Ternary Chains

React conditional rendering shouldn't be a mess of nested ternaries. Learn how to use guard clauses and declarative patterns to keep your UI logic clean.

Read more