Can’t Perform a React State Update on an Unmounted Component

While working on a React project, I ran into a warning that said:

“Can’t perform a React state update on an unmounted component.”

At first, it looked harmless, but I quickly realized it could lead to memory leaks and unpredictable behavior in my app.

Since I’ve spent more than a decade writing Python and JavaScript code, I’ve learned that these small warnings often point to bigger problems. So, I decided to dig deeper and fix it the right way.

In this tutorial, I’ll show you the exact methods I used to solve this issue. I’ll also share complete code examples, so you can copy and test them in your own projects.

Why Does This Warning Happen?

This warning appears when you try to update the state of a component after it has already been unmounted.

A common case is when you fetch data or set a timeout, but the component is removed before the task finishes. React then complains because it doesn’t make sense to update a component that no longer exists.

Method 1 – Use useEffect Cleanup

The simplest way to fix this issue is to cancel subscriptions or async tasks inside the cleanup function of useEffect.

Here’s a complete example:

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

function UserProfile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let isMounted = true;

    fetch("https://jsonplaceholder.typicode.com/users/1")
      .then((res) => res.json())
      .then((data) => {
        if (isMounted) {
          setUser(data);
        }
      });

    return () => {
      isMounted = false; // cleanup
    };
  }, []);

  if (!user) return <p>Loading user...</p>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  );
}

export default UserProfile;

I executed the above example code and added the screenshot below.

fix Can’t Perform a React State Update on an Unmounted Component

In this example, I use a flag, isMounted, to check if the component is still active before updating the state. The cleanup function ensures React won’t try to update state after unmount.

Method 2 – Abort Fetch Requests

Another reliable way is to use the AbortController API to cancel fetch requests when the component unmounts.

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

function WeatherWidget() {
  const [weather, setWeather] = useState(null);

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

    fetch("https://api.open-meteo.com/v1/forecast?latitude=40.71&longitude=-74.01&current_weather=true", {
      signal: controller.signal,
    })
      .then((res) => res.json())
      .then((data) => setWeather(data.current_weather))
      .catch((err) => {
        if (err.name !== "AbortError") {
          console.error(err);
        }
      });

    return () => controller.abort();
  }, []);

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

  return (
    <div>
      <h2>NYC Weather</h2>
      <p>Temperature: {weather.temperature}°C</p>
    </div>
  );
}

export default WeatherWidget;

I executed the above example code and added the screenshot below.

React Can’t Perform a React State Update on an Unmounted Component

Here, the AbortController stops the fetch request if the component unmounts. This avoids wasted network calls and prevents React from updating unmounted components.

Method 3 – Cancel Timers and Intervals

If you’re using setTimeout or setInterval, you should always clear them in the cleanup function.

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

function Clock() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const timer = setInterval(() => {
      setTime(new Date());
    }, 1000);

    return () => clearInterval(timer); // cleanup
  }, []);

  return (
    <div>
      <h2>Current Time</h2>
      <p>{time.toLocaleTimeString("en-US")}</p>
    </div>
  );
}

export default Clock;

I executed the above example code and added the screenshot below.

fix Can’t Perform a React State Update on an Unmounted Component in React

I used clearInterval in the cleanup to stop updating the state after the component unmounts. Without this, React would trigger the warning when the timer tries to update the state.

Method 4 – Use Libraries like React Query

In larger apps, managing async calls manually can get messy. I’ve had great success using React Query, which automatically cancels requests when components unmount.

import React from "react";
import { useQuery } from "@tanstack/react-query";

function PostsList() {
  const { data, isLoading, error } = useQuery(["posts"], () =>
    fetch("https://jsonplaceholder.typicode.com/posts").then((res) => res.json())
  );

  if (isLoading) return <p>Loading posts...</p>;
  if (error) return <p>Error fetching posts</p>;

  return (
    <div>
      <h2>Latest Posts</h2>
      <ul>
        {data.slice(0, 5).map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default PostsList;

React Query handles cancellations and state updates internally. This saves me from writing manual cleanup logic for every fetch.

Key Takeaways

  • The warning means React is trying to update a component that no longer exists.
  • Always clean up async tasks, subscriptions, and timers in useEffect.
  • Use AbortController for fetch requests and clearInterval for timers.
  • For bigger apps, libraries like React Query simplify state management and prevent leaks.

I hope you found these methods useful. I’ve personally used all of them in real-world projects, and they’ve saved me hours of debugging. If you follow these practices, you’ll keep your React apps clean, efficient, and free from memory leaks.

You may also read:

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.