How to fix Warning: Expected the listening component to be mounted but it was not in React

ReactINTERMEDIATEMEDIUMUpdated Dec 9, 2025ยท 106 views

This warning occurs when React attempts to update or interact with a component that has already been unmounted from the DOM. It typically happens when asynchronous operations like timers, API calls, or event listeners complete after the component has been removed, causing memory leaks and potential crashes.

Quick fix

Fixes Warning: Expected the listening component to be mounted but it was not

// WRONG - no cleanup
useEffect(() => {
  window.addEventListener("resize", handleResize);
}, []);

// CORRECT - cleanup function removes listener
useEffect(() => {
  window.addEventListener("resize", handleResize);
  
  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, []);
  1. Add cleanup functions to useEffect hooks
  2. Clear timers and intervals on unmount
  3. Cancel fetch requests and async operations
  4. Close WebSocket and real-time connections
react โ€” error
// WRONG - no cleanup
useEffect(() => {
window.addEventListener("resize", handleResize);
}, []);
// CORRECT - cleanup function removes listener
useEffect(() => {
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
Warning: Expected the listening component to be mounted but it was not

What this error means

React components have a lifecycle: they mount (appear in the DOM), update (re-render), and unmount (get removed from the DOM). When a component unmounts, it should no longer receive updates or handle events. This warning appears when code tries to interact with a component after it has been removed from the DOM. The most common scenario is an asynchronous operation (like a setTimeout, fetch request, or event listener) that completes after the component has unmounted. When the callback tries to update state or trigger an action, React detects that the component no longer exists and issues this warning. This indicates a memory leak and improper cleanup that can degrade performance and cause unexpected behavior.

Typical symptoms

  • Console warnings mentioning "listening component to be mounted" during navigation or component unmounting
  • Memory usage increasing over time as unused listeners accumulate
  • State updates attempting to run on components that are no longer visible
  • Event handlers firing after navigating away from a page or closing a modal
  • Timers or intervals continuing to run after component removal
  • Fetch requests completing and trying to update state after component unmounts
  • WebSocket messages or real-time updates triggering actions on removed components

Common causes

  1. Event listeners added with addEventListener not being removed with removeEventListener in cleanup
  2. setTimeout or setInterval callbacks executing after component unmounts without proper cleanup
  3. Fetch requests or API calls completing after the component has been removed from the DOM
  4. WebSocket connections or real-time subscriptions not being closed when component unmounts
  5. useEffect hooks without return cleanup functions for async operations
  6. Third-party libraries or custom hooks that set up subscriptions without cleanup
  7. Global event listeners on window or document that are not removed during unmount
  8. Promises that resolve after component unmount and attempt to call setState

How to fix "Warning: Expected the listening component to be mounted but it was not"

1Add cleanup functions to useEffect hooks

Every useEffect that sets up subscriptions, timers, or event listeners must return a cleanup function. This function runs when the component unmounts, ensuring all listeners are removed and operations are cancelled.

typescript
// WRONG - no cleanup
useEffect(() => {
  window.addEventListener("resize", handleResize);
}, []);

// CORRECT - cleanup function removes listener
useEffect(() => {
  window.addEventListener("resize", handleResize);
  
  return () => {
    window.removeEventListener("resize", handleResize);
  };
}, []);
2Clear timers and intervals on unmount

If you use setTimeout or setInterval, store the timer ID and clear it in the cleanup function. This prevents callbacks from executing after the component is gone.

typescript
useEffect(() => {
  const timerId = setTimeout(() => {
    setData(fetchedData);
  }, 1000);
  
  return () => {
    clearTimeout(timerId);
  };
}, []);

// For intervals
useEffect(() => {
  const intervalId = setInterval(() => {
    updateCounter();
  }, 1000);
  
  return () => {
    clearInterval(intervalId);
  };
}, []);
3Cancel fetch requests and async operations

Use AbortController to cancel in-flight fetch requests when the component unmounts. For other async operations, use a boolean flag to track if the component is still mounted.

typescript
// Using AbortController for fetch
useEffect(() => {
  const controller = new AbortController();
  
  fetch("/api/data", { signal: controller.signal })
    .then(res => res.json())
    .then(data => setData(data))
    .catch(err => {
      if (err.name !== "AbortError") {
        console.error(err);
      }
    });
  
  return () => {
    controller.abort();
  };
}, []);

// Using mounted flag for other async operations
useEffect(() => {
  let isMounted = true;
  
  asyncOperation().then(result => {
    if (isMounted) {
      setData(result);
    }
  });
  
  return () => {
    isMounted = false;
  };
}, []);
4Close WebSocket and real-time connections

If your component uses WebSockets, Socket.IO, or other real-time connections, close them in the cleanup function.

typescript
useEffect(() => {
  const socket = new WebSocket("wss://api.example.com");
  
  socket.onmessage = (event) => {
    setMessages(prev => [...prev, event.data]);
  };
  
  return () => {
    socket.close();
  };
}, []);

// For Socket.IO
useEffect(() => {
  const socket = io("https://api.example.com");
  
  socket.on("message", handleMessage);
  
  return () => {
    socket.off("message", handleMessage);
    socket.disconnect();
  };
}, []);
5Unsubscribe from third-party libraries

Many libraries like RxJS, Redux, or custom observables return an unsubscribe function. Store this function and call it in your cleanup.

typescript
import { Subject } from "rxjs";

useEffect(() => {
  const subject = new Subject();
  
  const subscription = subject.subscribe(data => {
    setData(data);
  });
  
  return () => {
    subscription.unsubscribe();
  };
}, []);
6Ensure event listener reference matches for removal

When adding and removing event listeners, you must use the exact same function reference. Do not use inline anonymous functions if you need to remove the listener later.

typescript
// WRONG - different function references
useEffect(() => {
  window.addEventListener("scroll", () => handleScroll());
  
  return () => {
    window.addEventListener("scroll", () => handleScroll()); // Won't work!
  };
}, []);

// CORRECT - same function reference
useEffect(() => {
  const handler = () => handleScroll();
  window.addEventListener("scroll", handler);
  
  return () => {
    window.removeEventListener("scroll", handler);
  };
}, []);
7Test component unmounting behavior

Navigate away from your component or conditionally render it to trigger unmounting. Check the console for warnings and verify that all timers, listeners, and connections are properly cleaned up. Use React DevTools Profiler to identify components with cleanup issues.

Advanced notes

Memory leaks from unmounted components are a common source of performance degradation in React applications, especially in single-page applications where components frequently mount and unmount. Each missed cleanup accumulates listeners and timers in memory. In class components, cleanup was handled in componentWillUnmount, but with hooks, the cleanup function returned from useEffect serves the same purpose. For complex applications, consider creating custom hooks that encapsulate subscription logic and cleanup, ensuring consistent patterns across your codebase. Libraries like react-use provide pre-built hooks with proper cleanup for common scenarios like event listeners, intervals, and async operations. In production builds with minified code, these warnings may be harder to debug, so always test cleanup logic in development. React Strict Mode in development intentionally mounts, unmounts, and remounts components to help catch these issues early. If you see this warning frequently, audit all useEffect hooks in your application for missing cleanup functions.

Frequently asked questions

What does "Warning: Expected the listening component to be mounted but it was not" mean?
React components have a lifecycle: they mount (appear in the DOM), update (re-render), and unmount (get removed from the DOM). When a component unmounts, it should no longer receive updates or handle events. This warning appears when code tries to interact with a component after it has been removed from the DOM.
How do I fix "Warning: Expected the listening component to be mounted but it was not"?
This warning occurs when React attempts to update or interact with a component that has already been unmounted from the DOM. It typically happens when asynchronous operations like timers, API calls, or event listeners complete after the component has been removed, causing memory leaks and potential crashes.
What causes "Warning: Expected the listening component to be mounted but it was not"?
Event listeners added with addEventListener not being removed with removeEventListener in cleanup setTimeout or setInterval callbacks executing after component unmounts without proper cleanup Fetch requests or API calls completing after the component has been removed from the DOM
Is the "Warning: Expected the listening component to be mounted but it was not" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading