When you fire a Promise it might take a few seconds before it resolves and by that time user might have navigated to another place in your app. So when Promise resolves setState is executed on unmounted component and you get an error - just like in your case. This may also cause memory leaks.

That's why it is best to move some of your asynchronous logic out of components.

Otherwise, you will need to somehow cancel your Promise. Alternatively - as a last resort technique (it's an antipattern) - you can keep a variable to check whether the component is still mounted:

componentDidMount(){
  this.mounted = true;

  this.props.fetchData().then((response) => {
    if(this.mounted) {
      this.setState({ data: response })
    }
  })
}

componentWillUnmount(){
  this.mounted = false;
}

I will stress that again - this is an antipattern but may be sufficient in your case (just like they did with Formik implementation).

A similar discussion on GitHub

EDIT:

This is probably how would I solve the same problem (having nothing but React) with Hooks:

OPTION A:

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

export default function Page() {
  const value = usePromise("https://something.com/api/");
  return (
    <p>{value ? value : "fetching data..."}</p>
  );
}

function usePromise(url) {
  const [value, setState] = useState(null);

  useEffect(() => {
    let isMounted = true; // track whether component is mounted

    request.get(url)
      .then(result => {
        if (isMounted) {
          setState(result);
        }
      });

    return () => {
      // clean up
      isMounted = false;
    };
  }, []); // only on "didMount"

  return value;
}

OPTION B: Alternatively with useRef which behaves like a static property of a class which means it doesn't make component rerender when it's value changes:

function usePromise2(url) {
  const isMounted = React.useRef(true)
  const [value, setState] = useState(null);


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

  useEffect(() => {
    request.get(url)
      .then(result => {
        if (isMounted.current) {
          setState(result);
        }
      });
  }, []);

  return value;
}

// or extract it to custom hook:
function useIsMounted() {
  const isMounted = React.useRef(true)

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

  return isMounted; // returning "isMounted.current" wouldn't work because we would return unmutable primitive
}

Example: https://codesandbox.io/s/86n1wq2z8

Answer from Tomasz Mularczyk on Stack Overflow
Top answer
1 of 16
119

When you fire a Promise it might take a few seconds before it resolves and by that time user might have navigated to another place in your app. So when Promise resolves setState is executed on unmounted component and you get an error - just like in your case. This may also cause memory leaks.

That's why it is best to move some of your asynchronous logic out of components.

Otherwise, you will need to somehow cancel your Promise. Alternatively - as a last resort technique (it's an antipattern) - you can keep a variable to check whether the component is still mounted:

componentDidMount(){
  this.mounted = true;

  this.props.fetchData().then((response) => {
    if(this.mounted) {
      this.setState({ data: response })
    }
  })
}

componentWillUnmount(){
  this.mounted = false;
}

I will stress that again - this is an antipattern but may be sufficient in your case (just like they did with Formik implementation).

A similar discussion on GitHub

EDIT:

This is probably how would I solve the same problem (having nothing but React) with Hooks:

OPTION A:

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

export default function Page() {
  const value = usePromise("https://something.com/api/");
  return (
    <p>{value ? value : "fetching data..."}</p>
  );
}

function usePromise(url) {
  const [value, setState] = useState(null);

  useEffect(() => {
    let isMounted = true; // track whether component is mounted

    request.get(url)
      .then(result => {
        if (isMounted) {
          setState(result);
        }
      });

    return () => {
      // clean up
      isMounted = false;
    };
  }, []); // only on "didMount"

  return value;
}

OPTION B: Alternatively with useRef which behaves like a static property of a class which means it doesn't make component rerender when it's value changes:

function usePromise2(url) {
  const isMounted = React.useRef(true)
  const [value, setState] = useState(null);


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

  useEffect(() => {
    request.get(url)
      .then(result => {
        if (isMounted.current) {
          setState(result);
        }
      });
  }, []);

  return value;
}

// or extract it to custom hook:
function useIsMounted() {
  const isMounted = React.useRef(true)

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

  return isMounted; // returning "isMounted.current" wouldn't work because we would return unmutable primitive
}

Example: https://codesandbox.io/s/86n1wq2z8

2 of 16
31

The friendly people at React recommend wrapping your fetch calls/promises in a cancelable promise. While there is no recommendation in that documentation to keep the code separate from the class or function with the fetch, this seems advisable because other classes and functions are likely to need this functionality, code duplication is an anti-pattern, and regardless the lingering code should be disposed of or canceled in componentWillUnmount(). As per React, you can call cancel() on the wrapped promise in componentWillUnmount to avoid setting state on an unmounted component.

The provided code would look something like these code snippets if we use React as a guide:

const makeCancelable = (promise) => {
    let hasCanceled_ = false;

    const wrappedPromise = new Promise((resolve, reject) => {
        promise.then(
            val => hasCanceled_ ? reject({isCanceled: true}) : resolve(val),
            error => hasCanceled_ ? reject({isCanceled: true}) : reject(error)
        );
    });

    return {
        promise: wrappedPromise,
        cancel() {
            hasCanceled_ = true;
        },
    };
};

const cancelablePromise = makeCancelable(fetch('LINK HERE'));

constructor(props){
    super(props);
    this.state = {
        isLoading: true,
        dataSource: [{
            name: 'loading...',
            id: 'loading',
        }]
    }
}

componentDidMount(){
    cancelablePromise.
        .then((response) => response.json())
        .then((responseJson) => {
            this.setState({
                isLoading: false,
                dataSource: responseJson,
            }, () => {

            });
        })
        .catch((error) =>{
            console.error(error);
        });
}

componentWillUnmount() {
    cancelablePromise.cancel();
}

---- EDIT ----

I have found the given answer may not be quite correct by following the issue on GitHub. Here is one version that I use which works for my purposes:

export const makeCancelableFunction = (fn) => {
    let hasCanceled = false;

    return {
        promise: (val) => new Promise((resolve, reject) => {
            if (hasCanceled) {
                fn = null;
            } else {
                fn(val);
                resolve(val);
            }
        }),
        cancel() {
            hasCanceled = true;
        }
    };
};

The idea was to help the garbage collector free up memory by making the function or whatever you use null.

🌐
GitHub
gist.github.com › viclafouch › 91e4782d6831a2cf95def05eba80db11
A React component that fetching data on mount and avoiding memory leaks on unmount with AbortController · GitHub
A React component that fetching data on mount and avoiding memory leaks on unmount with AbortController - abort-requests-in-react.js
Discussions

How important is it to cancel network requests when a component unmounts?
i personally say it is required. usually when you make a network call you are also dispatching it to some state management. if that is a useState and you have unmounted, you will throw an exception when it attempts to set that state. redux would be fine, recoil would be as well unless the recoil root was also unmounted, same for context. i feel it is just easier to always handle this at the start and not worry about if it was handled correctly later. just my opinion though More on reddit.com
🌐 r/reactjs
11
2
February 19, 2023
react native - abort fetch when component unmount - Stack Overflow
how could I cancel fetch operation when component go away (unmount) example : user open this screen and go back before fetch complete here is what I have done export default class LecturesScreen More on stackoverflow.com
🌐 stackoverflow.com
July 20, 2017
Cancelling promises and network calls on components unmounting?
You can't cancel native promises. There are promise libraries which provide provide cancelling capabilities like bluebird. More on reddit.com
🌐 r/reactjs
15
6
February 5, 2017
Do I need to manage fetch cancellations? Or does React handle this?
This is more of a general Javascript question,. React itself has little to no opinion on how your fetch requests are made. My experience is that most devs just ignore the response from a request that isn't relevant anymore, which does work most of the time, but if you want to be really clean about it you're looking for the AbortController API: https://developer.mozilla.org/en-US/docs/Web/API/AbortController More on reddit.com
🌐 r/reactjs
8
18
September 22, 2021
🌐
GitHub
gist.github.com › aderbas › 187c3ed23db7d6ece9748a5858a8f0d5
Cancel fetch when React component will unmount · GitHub
December 17, 2021 - Cancel fetch when React component will unmount. GitHub Gist: instantly share code, notes, and snippets.
🌐
Medium
medium.com › @jlangkammer › how-to-create-a-reusable-hoc-that-aborts-fetch-requests-on-component-unmount-in-react-c2b539a8d0e
How to Create a Reusable HOC That Aborts Fetch Requests on Component Unmount in React | by Jon Langkamer | Medium
July 30, 2019 - When the video component unmounts, so will the HOC, which will cause the state in the HOC to change. This HOC state change will cause any pending fetch request happening in the video component to terminate since this signal is being passed down ...
🌐
Reddit
reddit.com › r/reactjs › how important is it to cancel network requests when a component unmounts?
r/reactjs on Reddit: How important is it to cancel network requests when a component unmounts?
February 19, 2023 -

If a fetch request keeps running after a component has unmounted, we are wasting resources because we don't have a use for the return value of that request anymore (since the component showing the data was removed).

I'm trying to understand if request cancellation is considered merely an "optimization" or absolutely important. Assuming that the request doesn't do anything particularly expensive, just a database request on the backend.

Also, what about POST and PATCH requests? Don't we wanna finish these even if we navigated away?

And what about libraries like React-query and SWR that cache the response? Does the caching make it okay to load an unused response, considering that we can reuse it later to show cached data?

🌐
Westbrookdaniel
westbrookdaniel.com › blog › react-abort-controllers
Using AbortControllers to Cancel Fetch in React - Daniel Westbrook
What does this mean? update on an unmounted component summarizes it well. We are trying to change the state of a component that no longer exists, because it was removed. This can lead to our app breaking in weird ways, as well as wasting resources on unnecessary actions. So let's fix it by canceling the fetch. useEffect(() => { const controller = new AbortController(); fetch("https://jsonplaceholder.typicode.com/posts/1", { signal: controller.signal, }) .then((res) => res.json()) .then((json) => setMessage(json.title)) .catch((error) => console.error(error.message)); return () => controller.abort(); }, []);
🌐
React Discuss
discuss.reactjs.org › t › cancel-async-fetch-on-unmount › 3272
Cancel async fetch on unmount - React Discuss
February 26, 2016 - fetchBookings: function () { ... this.xhr = $.ajax(stuff) } componentWillUnmount: function () { this.xhr.abort() } markbrown4 (Mark Brown) 2016-03-04 02:02:02 UTC #6 · Thanks for these, I noticed deprecation warnings when trying to use isMounted(). I’m using this in react-native which promotes the fetch api, but it does have XMLHttpRequest too https://facebook.github.io/react-native/docs/network.html#xmlhttprequest so I may need to use that if I need to abort requests.
Find elsewhere
🌐
Plain English
plainenglish.io › blog › how-to-cancel-fetch-and-axios-requests-in-react-useeffect-hook
How to Cancel Fetch and Axios Requests in React’s useEffect Hook
October 20, 2023 - In the cleanup function provided by useEffect, we use source.cancel() to terminate the Axios request when the component unmounts, preventing unnecessary state updates. This code achieves the same functionality as the Fetch example but with Axios ...
🌐
Hamon
hamon.in › blog › mastering-abortcontroller-in-react-canceling-requests-made-simple
Mastering AbortController in React: Canceling Requests ...
Let’s start with a simple fetch request in a React component. We’ll use AbortController to cancel it when the component unmounts.
🌐
DEV Community
dev.to › rodw1995 › cancel-your-promises-when-a-component-unmounts-gkl
Cancel your promises when a component unmounts - DEV Community
March 21, 2020 - But if we receive a promise and it is out of our control as to whether we can make it settle, then that TrashablePromise idea (or CancelablePromise from that GitHub issue) is the next best option, and in that case we can only hope the externally provided Promise will sometime settle. Regarding the Fetch API, it has an Abort API which we can take advantage of to cancel the network operation, and we should make sure to reject any promises that we may have handed to any other code.
🌐
GitHub
github.com › expo › use-unmount-signal
GitHub - expo/use-unmount-signal: A React Hook to cancel promises when a component is unmounted
A React Hook that returns an AbortSignal object that is marked as aborted when the calling component is unmounted. import useUnmountSignal from 'use-unmount-signal'; function Example() { // useUnmountSignal returns an AbortSignal object that ...
Starred by 294 users
Forked by 8 users
Languages   TypeScript 85.7% | Shell 11.6% | JavaScript 2.7% | TypeScript 85.7% | Shell 11.6% | JavaScript 2.7%
🌐
DEV Community
dev.to › viclafouch › cancel-properly-http-requests-in-react-hooks-and-avoid-memory-leaks-pd7
🍦 Cancel Properly HTTP Requests in React Hooks and avoid Memory Leaks 🚨 - DEV Community
August 2, 2020 - So let's useEffect to subscribe to our fetch request and to avoid memory leaks. We use the clean method of useEffect for calling abort() when our component unmount. Now, no more memory leaks! 😍 · As always, feel free to reach out to me! 😉 · You can check this demo on abort-with-react-hooks.vercel.app.
🌐
Dmitri Pavlutin
dmitripavlutin.com › react-cleanup-async-effects
How to Cleanup Async Effects in React
May 25, 2021 - When the callback function returns a function, React will use that as a cleanup function: ... Also, in order to cancel an active fetch request, you need to use an AbortController instance.
🌐
Robwise
robwise.github.io › blog › cancel-whatwg-fetch-requests-in-react
Aborting Fetch Requests in React
February 22, 2018 - This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the undefined component. Dan Abramov recommends cancelling the request so that the then never fires. Axios has support for this out of the box, but if you’re using the WHATWG-Fetch standard (via its polyfill), you will need to do a bit more work.
🌐
j-labs
j-labs.pl › home › tech blog › how to use the useeffect hook with the abortcontroller
AbortController in React. How to use the useEffect hook with the AbortControl? | j‑labs
December 9, 2025 - The useEffect hook in React allows ... updates, or unmounts. By integrating AbortController with useEffect, we can cancel ongoing requests when the component unmounts or when a dependency changes....
🌐
LogRocket
blog.logrocket.com › home › understanding react’s useeffect cleanup function
Understanding React’s useEffect cleanup function - LogRocket Blog
December 16, 2024 - So, we must abort the fetch using the cleanup function. Let’s say we have a React component that fetches and renders data. If our component unmounts before our promise resolves, useEffect will try to update the state (on an unmounted component) ...
🌐
Medium
medium.com › @icjoseph › using-react-to-understand-abort-controllers-eb10654485df
Using React to understand Abort Controllers | by Joseph Chamochumbi | Medium
November 18, 2022 - If there’s an ongoing asynchronous process and we toggle down the Resource component, then the asynchronous process resolves on an already unmounted component. This triggers a React warning. Let’s create a mechanism to cancel the process of getting the random, pseudo-unique id. Listen to the abort event on the signal.
🌐
YouTube
youtube.com › watch
Cancel the fetch request to avoid setting state on an unmounted component - YouTube
Learn how to cancel a fetch request to avoid setting the state on an unmounted component using the AbortController API instead of using useRef().➡️ The Ultim...
Published   November 5, 2022
🌐
Medium
rajeshnaroth.medium.com › writing-a-react-hook-to-cancel-promises-when-a-component-unmounts-526efabf251f
Writing a React hook to cancel promises when a component unmounts. | by Rajesh Naroth | Medium
January 3, 2023 - We’ll build this hook a bit further ... cancellablePromise(getJson(url)); That’s it. The cancelable promise hook will take care of the clean up when the component is unMounted....