DEV Community

Igor Quirino
Igor Quirino

Posted on • Originally published at wareboss.com

React Hook - Clean Up useEffect

From: https://wareboss.com/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
    };
}, []);
Enter fullscreen mode Exit fullscreen mode

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;
    };
  }, [...]);
Enter fullscreen mode Exit fullscreen mode

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);
}, []);
Enter fullscreen mode Exit fullscreen mode

Imagine this use case: you opened this component and then closed.
Withou clean up you will continues running the setInterval callback.


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
 }, []);
Enter fullscreen mode Exit fullscreen mode

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]);
Enter fullscreen mode Exit fullscreen mode

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!

Top comments (4)

Collapse
 
katnel20 profile image
Info Comment hidden by post author - thread only accessible via permalink
Katie Nelson

Hi Igor, I'm Katie, one of the basic moderators here on DEV.
My unofficial title: DEV cheerleader šŸ˜Š

I want to welcome you to the DEV community and let you know that you'll find lots of help and support here for all your coding needs.

Don't hesitate to ask questions.
It's great to see you are already contributing new posts!

Collapse
 
iquirino profile image
Igor Quirino

Hello! Thank you, i appreciate you attention.
Bye bye!

Collapse
 
devopshasan profile image
Hasan Habib

Thank you for this awesome post!

Collapse
 
tulkasastaldo9 profile image
Tulkas Astaldo

super helpful post! thanks so much!

Some comments have been hidden by the post's author - find out more