How to Handle React Component Unmount 

Recently, while working on a React project that fetched live stock data from a U.S. financial API, I ran into a frustrating issue: my app threw the warning: “Can’t perform a React state update on an unmounted component.”

At first, this message confused me. I thought my code was fine because the data was fetching correctly. But after navigating between pages quickly, React started complaining. That’s when I realized I wasn’t handling the component unmount properly.

In this tutorial, I’ll show you two simple and effective ways to handle component unmounts in React. Both methods come from my own experience debugging real-world React apps.

What Does “Component Unmount” Mean in React?

When a component unmounts, it means React removes it from the DOM. This usually happens when the user navigates away from a page or when a component is conditionally hidden.

If you try to update state (using setState or useState) after the component has unmounted, React will warn you, because there’s no component left to update.

This is common when you’re fetching data asynchronously (like from an API) and the response arrives after the component has already unmounted.

Why React Warns About State Updates After Unmount

React does this to prevent memory leaks.

Imagine this:
You fetch stock data for a dashboard, but the user navigates away before the data arrives.
If your code still tries to update the state, React has nowhere to apply that update; the component is gone.
That’s when you see the warning.

Method 1 – Use useEffect Cleanup Function

The most common and recommended way to handle component unmounts is by using the cleanup function inside the useEffect hook.

Here’s how I handle it in my own projects.

Example: Handle Component Unmount with Cleanup

import React, { useState, useEffect } from "react";

function StockData() {
  const [data, setData] = useState([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let isMounted = true; // flag to track component mount status

    async function fetchStockData() {
      try {
        const response = await fetch("https://api.example.com/us-stocks");
        const result = await response.json();
        if (isMounted) {
          setData(result);
          setLoading(false);
        }
      } catch (error) {
        console.error("Error fetching stock data:", error);
      }
    }

    fetchStockData();

    // Cleanup function runs when component unmounts
    return () => {
      isMounted = false;
      console.log("Component unmounted, cleanup done!");
    };
  }, []);

  if (loading) return <p>Loading stock data...</p>;

  return (
    <div>
      <h2>U.S. Stock Market Data</h2>
      <ul>
        {data.map((stock) => (
          <li key={stock.symbol}>
            {stock.symbol}: ${stock.price}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default StockData;

You can refer to the screenshot below to see the output.

Handle React Component Unmount
  • The isMounted flag ensures that we only call setData() if the component is still mounted.
  • When the component unmounts, the cleanup function sets isMounted to false.
  • This prevents React from trying to update the state of an unmounted component.

Method 2 – Use an AbortController (Best for Fetch Requests)

When you’re working with fetch requests, a cleaner way to handle unmounts is by using the AbortController API. This cancels the fetch request if the component unmounts before the request completes.

Example: Use AbortController to Cancel Fetch

import React, { useState, useEffect } from "react";

function WeatherData() {
  const [weather, setWeather] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;

    async function fetchWeather() {
      try {
        const response = await fetch("https://api.weather.gov/gridpoints/OKX/33,37/forecast", { signal });
        const data = await response.json();
        setWeather(data);
        setLoading(false);
      } catch (error) {
        if (error.name === "AbortError") {
          console.log("Fetch aborted due to component unmount");
        } else {
          console.error("Error fetching weather data:", error);
        }
      }
    }

    fetchWeather();

    // Cleanup function to abort fetch on unmount
    return () => {
      controller.abort();
    };
  }, []);

  if (loading) return <p>Loading weather data...</p>;

  return (
    <div>
      <h2>New York Weather Forecast</h2>
      <p>{weather.properties.periods[0].detailedForecast}</p>
    </div>
  );
}

export default WeatherData;

You can refer to the screenshot below to see the output.

How to Handle React Component Unmount
  • We create an AbortController before making the fetch request.
  • The fetch call includes signal as an option.
  • When the component unmounts, the cleanup function calls controller.abort().
  • This cancels the fetch request, preventing any state updates after unmount.

Method 3 – Use a Custom Hook for Cleanup Logic

If you find yourself handling unmounts in multiple components, you can move this logic into a custom hook.

Example: Reusable Custom Hook

import { useEffect, useRef } from "react";

export function useIsMounted() {
  const isMounted = useRef(false);

  useEffect(() => {
    isMounted.current = true;
    return () => (isMounted.current = false);
  }, []);

  return isMounted;
}

Now you can use this hook in any component:

import React, { useState, useEffect } from "react";
import { useIsMounted } from "./useIsMounted";

function CryptoPrices() {
  const [prices, setPrices] = useState([]);
  const isMounted = useIsMounted();

  useEffect(() => {
    async function fetchCrypto() {
      const response = await fetch("https://api.coindesk.com/v1/bpi/currentprice.json");
      const data = await response.json();
      if (isMounted.current) {
        setPrices(data);
      }
    }
    fetchCrypto();
  }, [isMounted]);

  return (
    <div>
      <h2>Bitcoin Price (USD)</h2>
      <p>${prices?.bpi?.USD?.rate}</p>
    </div>
  );
}

export default CryptoPrices;

You can refer to the screenshot below to see the output.

Handle Component Unmount in React
  • Keeps your code DRY (Don’t Repeat Yourself).
  • Makes it easy to reuse the same unmount-handling logic across multiple components.

Common Mistakes to Avoid

  1. Not cleaning up subscriptions – If you’re using WebSockets, timers, or event listeners, always remove them in the cleanup function.
  2. Updating state after navigation – If your component fetches data, check if it’s still mounted before calling setState.
  3. Ignoring warnings – The “Can’t perform a React state update on an unmounted component” warning is a helpful signal. Don’t just suppress it, fix it.

Pro Tip

If you’re using modern libraries like React Query or SWR, they handle unmount logic automatically. But if you’re writing your own fetch logic, always use one of the methods above to prevent memory leaks.

When I first encountered this issue, it took me a while to understand why React was warning me. But once I learned how to handle component unmounts properly using cleanup functions or AbortController, my apps became much more stable, especially when working with real-time APIs.

Both methods work great; the cleanup function method is simple and works in most cases, while AbortController is perfect for fetch requests.

You may also read other React articles:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.