React Hook – Clean Up useEffect

Last article we learn about Asynchronous actions on useEffect and our correct usage (React Hook – Async funcion in useEffect).

Today we will see how to use the clean up function of useEffect React Hook.

When you update a state from an unmounted component, React will throw this error:

“Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.”

useEffect(() => {
    //Do all the job, for example, subscribe a websocket channel
    return function(){
        //Unsubscribe websocket channel
    };
}, []);

Prevent update on unmounted component:

Here you’ll learn how to prevent this problem

  useEffect(() => {
    let isCancelled = false;
    const runAsync = async () => {
      try {
        if (!isCancelled) {
          // do the job
        }
      } catch (e) {
        if (!isCancelled) {
          throw e;
        }
      }
    };

    runAsync();

    return () => {
      isCancelled = true;
    };
  }, [...]);

Usage with setInterval/setTimeout:

This is a nice solution to abort setInterval/setTimeout:

useEffect(() => {
  const interval = setInterval(() => {
    console.log('Five Seconds!');
  }, 5000);
  return () => clearInterval(interval);
}, []);

Imagine this use case: you opened this component and then closed.
Without clean

Without cleanup the setInterval will keeps running.


Usage with Firestore Realtime Database:

This is useful when using Firestore Realtime Database:

useEffect(() => {
    //Subscribe: firebase channel
    const cleanUp = firebase.firestore().collection('photos') .doc(id)
        .onSnapshot( doc => {
            setLoading(false);
            setPhotos(doc)
        }, err => { setError(err); }
    );
    return () => cleanUp(); //Unsubscribe
 }, []);

If you forgot to clean your firestore subscription, you may receive unnecessary requests.


Usage with fetch + AbortController:

Cancel fecth with AbortController from fetch/es6:

  useEffect(() => {
    const abortController = new AbortController();
    const fetchData = async () => {
      try {
        const ret = await fetch("/companies", { signal: abortController.signal });
        const data = await ret.json();
        // ...
      }
      catch(error) {
        if (abortController.signal.aborted) {
          // cancelled
        }
        else
          throw error;
      };
    };

    fetchData();

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

Usage with axios request:

Here is how to cancel the request with axios.

useEffect(() => {
  const source = axios.CancelToken.source();
 
  const fetchData = async () => {
    try {
      const response = await Axios.get("/companies", {
        cancelToken: source.token
      });
      // ...
    } catch (error) {
      if (Axios.isCancel(error)) {
        //cancelled
      } else {
        throw error;
      }
    }
  };

  fetchData()
 
  return () => {
    source.cancel();
  };
}, [companies]);

The useEffect function is the equivalent of componentDidMount in a React Class component.

The clean up function is the equivalent of componentWillUnmount in a React Class component.

Next article: React Class Component and React Function Component differences.

Bye bye!

9 thoughts on “React Hook – Clean Up useEffect

  1. Brian Reply

    This Axios example is the ONLY one that worked!!! Spent several hours ! Thank you for this write-up!

  2. Elenor Czaplicki Reply

    An outstanding share! I’ve just forwarded this onto a co-worker who was conducting a little research on this. And he in fact bought me lunch due to the fact that I stumbled upon it for him… lol. So let me reword this…. Thanks for the meal!! But yeah, thanx for spending time to talk about this topic here on your internet site.

  3. Carmon Hanan Reply

    Hello there. I discovered your web site by way of Google even as searching for a comparable subject, your web site got here up. It appears good. I have bookmarked it in my google bookmarks to visit then.

  4. Free Stuff Reply

    I’ve been browsing online more than 3 hours today, yet I never found any interesting article like yours. It?s pretty worth enough for me. In my view, if all site owners and bloggers made good content as you did, the web will be much more useful than ever before.

Leave a Reply

Your email address will not be published. Required fields are marked *