DEV Community

Robert Marshall
Robert Marshall

Posted on • Originally published at robertmarshall.dev on

Component Will Unmount How to use componentWillUnmount with Functional Components in React


Most up to date version of this article: https://robertmarshall.dev/blog/componentwillunmount-functional-components-react


Functional components are far more efficient than class based components. There is also less code that is needed to be written to achieve the same goal.

However, I could not get my head around how functional components could implement the use of life-cycle events without needing to be changed to a class.

Turns out everything can be managed through useEffect.

I have used useEffect in the past to manage API calls, and what happened on a componentWillMount, but never componentWillUnmount. It turns out both are very similar!

How to manage componentWillMount with useEffect

To understand how we can use componentWillUnmount, first we need to look at how the component manages mounting with useEffect.

import React, { useEffect } from 'react';
const ComponentExample => () => {
   useEffect( () => {
      // Anything in here is fired on component mount.
   }, []);
}
Enter fullscreen mode Exit fullscreen mode

If we pass an empty array as the second argument, it tells useEffect to fire on component load. This is the only time it will fire.

With this in mind, how can we alter the code to work with componentWillUnmount? Turns out the solution is very simple.

How to manage componentWillUnmount with useEffect

If you add a return function inside the useEffect function, it is triggered when a component unmounts from the DOM. This looks like:

import React, { useEffect } from 'react';
const ComponentExample => () => {
    useEffect(() => {
        return () => {
            // Anything in here is fired on component unmount.
        }
    }, [])
}
Enter fullscreen mode Exit fullscreen mode

Combining both solutions

This means that you can use componentDidMount, and componentWillUnmount in the same useEffect function call. Dramatically reducing the amount of code needed to manage both life-cycle events. Like so:

import React, { useEffect } from 'react';
const ComponentExample => () => {
    useEffect(() => {
        // Anything in here is fired on component mount.
        return () => {
            // Anything in here is fired on component unmount.
        }
    }, [])
}
Enter fullscreen mode Exit fullscreen mode

Top comments (19)

Collapse
 
sridhar_natuva profile image
sridhar.natuva

I want to display an dialog box on unmount and When user cancels it should stop unmounting the component.

Right now, even if user cancels or says ok, component will anyway unmount on return funtion.

Is there any way to stop unmount on the return function? Or any other approach?

Collapse
 
arnabmunshi profile image
ARNAB MUNSHI

Hi, I need a help

  componentDidMount() {  
    this._subscribe();
  }

  componentWillUnmount() {
    this._unsubscribe();
  }

  async _subscribe() {
    const batteryLevel = await Battery.getBatteryLevelAsync();
    this.setState({ batteryLevel });
    this._subscription = Battery.addBatteryLevelListener(({ batteryLevel }) => {
      this.setState({ batteryLevel });
      console.log('batteryLevel changed!', batteryLevel);
    });
  }

  _unsubscribe() {
    this._subscription && this._subscription.remove();
    this._subscription = null;
  }

How to convert this in functional component ?
I have done something like this ...

  const getLevel = async () => {
    console.log("A: " + (await Battery.getBatteryLevelAsync()));

    let batteryLevel = Math.round((await Battery.getBatteryLevelAsync()) * 100);
    setLevel(batteryLevel);
    Battery.addBatteryLevelListener(({ batteryLevel }) => {
      batteryLevel = Math.round(batteryLevel * 100);
      setLevel(batteryLevel);

      console.log("B: " + batteryLevel);
    });
  };

  useEffect(() => {
    // Anything in here is fired on component mount.
    // componentDidMount
    getLevel();

    // componentWillUnmount
    return () => {
      // Anything in here is fired on component unmount.
    };
  }, []);

I am facing problem in

return function

Collapse
 
robmarshall profile image
Robert Marshall

If you don't need anything to fire on component unmount, you can remove the return.

  useEffect(() => {
    getLevel();
  }, []);
Collapse
 
gopeeey profile image
gopeeey

Thank you very much for this

Collapse
 
amahecool profile image
amahecool • Edited

the returned function fires on component Re-render also. How to you check if its an unmount or just a re-render ?
Basically its just a clean up function which runs every time the useEffect is used (except the first time)

Collapse
 
kasir-barati profile image
Mohammad Jawad (Kasir) Barati • Edited

Are you sure? AFAIK it should not be the case, it's only triggered once the component is unmounting or remounting itself. So maybe you can check that out.

Also you might have other useEffect who are defined sooner and as you might know the order of defining useEffect hooks matter

Collapse
 
robmarshall profile image
Robert Marshall

I suppose you could use a useRef to track the render (it will not be cleaned on a rerender). Depends on what you need it to do.

Collapse
 
vladanpro profile image
Vladan Profirovic

import React, { useEffect } from 'react';
const ComponentExample => () => {
useEffect( () => {
// Anything in here is fired on component mount.
}, []);
}
hi srry this show me that is fired on component mount but not on will mount, so i try to find what is best solution to replace componentWillMount. Tnx.

Collapse
 
rahulbhadhoriya profile image
Rahul Bhadhoriya

Thanks very much

Collapse
 
omnislashbr profile image
Hector Bonilha

This is going to simulate componentDidUnmount, not componentWillUnmount

Collapse
 
kasir-barati profile image
Mohammad Jawad (Kasir) Barati

Hm, interesting. Can you explain it further in detail?

Collapse
 
shivam164 profile image
Shivam

Nice this is what I was searching for :).

Collapse
 
seojeek profile image
Alex Vallejo

"Parsing error: Unexpected token, expected ","" is what i get when i try to return that

Collapse
 
robmarshall profile image
Robert Marshall

Looks like you have a typo?

Collapse
 
pablobion profile image
Pablo Bion

Very cool!