DEV Community

loading...

React Hook - Clean Up useEffect

iquirino profile image Igor Quirino Originally published at wareboss.com ・3 min read

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!

Discussion (5)

Collapse
abdelrhmanamin profile image
Abdo Amin

Igor!!! Thank you so much!!!

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

Forem Open with the Forem app