
The Unmount Lifecycle
The unmount lifecycle lives outside of the main lifecycle, as it only comes into play when a component is removed from the DOM. This lifecycle is also far more limited, as the only lifecycle method it contains is componentWillUnmount().
componentWillUnmount()
componentWillUnmount() exists solely to perform and react to the component being removed from the DOM, and then is eventually removed entirely from existence. While it sounds a bit dramatic, it's important to note that this is what happens when a component is otherwise completely destroyed. It takes no arguments, and there are some caveats about using it.
The code for componentWillUnmount() might look something like this:
class App extends Component {
componentWillUnmount() {
alert("I've been removed!");
}
render() {
return (<p className="App">Hello World!</p>);
}
}
Now if something were to happen that would cause that component to no longer be displayed, we'd see a browser alert box pop up with the message I've been removed!.
When can a component be removed from the DOM, though? This can happen if you're building a list of components and one of the items in the list gets deleted in JavaScript and that component's JSX is no longer included in the rest of the JSX that is getting written to the browser. It can also happen if you are using conditional rendering and the condition that previously displayed the component is no longer true.
Since this is called only when a component is about to be removed from the DOM and tossed into the void, you probably shouldn't call any state or prop modification logic on it, nor set any new event handlers or anything that you'd want to do to a long-lived component.
Note
The only time this is called is before the component is unmounted, instead of after the operation, unlike componentDidMount and componentDidUpdate.
Exercise 4.04: Messaging on Unmount
We'll work through a quick exercise to quickly demonstrate the usage of componentWillUnmount. We'll build up a list of items, display them on the page, and then demonstrate what happens when each item is removed from the list, and thus the JSX is removed from the DOM.
- Start off by creating a new React project, which we will call will-unmount, start the project, and take a look at the browser window that should have opened for you automatically:
$ npx create-react-app will-unmount
$ cd will-unmount
$ yarn start
- Next, strip out the stuff we don't need. Delete src/logo.svg and delete the contents of src/App.css. Clean out the contents of the App component and replace it with a class component instead. Since we are using a class component here, we will need to change the import statement at the top to also import Component from React:
import React, { Component } from 'react';
import "./App.css";
class App extends Component {
render() {
return (
<p className="App">
<h1>My List</h1>
</p>
);
}
}
export default App;
Visit the app in your browser by going to http://localhost:3000.
- Next, set up the state in the constructor of the App component to be a list of items. Each item should have an ID and a message that we'll display to the user:
constructor(props) {
super(props);
this.state = {
list: [
{ id: 1, message: 'Hello' },
{ id: 2, message: 'Everyone' },
{ id: 3, message: 'What' },
{ id: 4, message: 'Is' },
{ id: 5, message: 'Up' }
]
};
}
- We will also need the component that our componentWillUnmount function will live in, so we will create a new component to display each message. Create this as src/Message.js. The message will be passed in via props, and we will also need a remove me button that we will flesh out later:
import React, { Component } from "react";
class Message extends Component {
render() {
return (
<p className="Message">
<p>{this.props.message}</p>
<button>Remove me</button>
</p>
);
}
}
export default Message;
- Next, return to our App component and import the Message component:
import Message from "./Message";
- In the render function, we'll display each of the components via a map statement:
render() {
return (
<p className="App">
<h1>My Items</h1>
{this.state.list.map(item => (
<Message
key={item.id}
id={item.id}
message={item.message}
/>
))}
</p>
);
}
- Now add a function that will remove the item from the list in state. It will need to accept an ID as its only argument and filter the list of items on the filter statement:
removeItem(id) {
const newList = this.state.list.filter(item => item.id !== id);
this.setState({ list: newList });
}
- Pass that removeMe function down to the Message component (in the render() function body) as one of its props:
{this.state.list.map(item => (
<Message
key={item.id}
id={item.id}
message={item.message}
removeItem={this.removeItem.bind(this)}
/>
))}
- Add a componentWillUnmount() function to our Message component that will just produce a console.log() statement indicating what component has been removed:
componentWillUnmount() {
console.log('Removing item', this.props);
}
- And finally, add the call to this.props.removeMe to the onClick handler for the button we added earlier:
<button onClick={() => this.props.removeItem(this.props.id)}>
Remove me
</button>
- Finally, confirm that everything is working, and messages are flowing into the console each time you remove a component, like in the following screenshot. The output is as follows:
Figure 4.10: React app component
Now, it's time to put into practice all the lifecycle method skills you have gained in the chapter with the upcoming activity.
Activity 4.01: Creating a Messaging App
In this activity, you're going to write an app that will simulate logging into a messaging application, loading your messages in the app based on what username you enter, and logging out, all of which should simulate a real app with AJAX calls but without the actual logic. This will help you get a feel for the sort of decisions you would need to make around the lifecycle in a real-world messaging application, where the user must be able to trust the behavior of the application. React's lifecycle methods give us a good way to provide that sort of seamless feel.
The following steps will help you achieve the activity:
- Create your React application.
- Simulate an Ajax request to export a few different utilities; a library has been provided for this AjaxLibrary.js. It can be found inside the src folder: https://packt.live/2N3BEoA.
- Create the base file UserCountDisplay.js where you'll need to use the constructor(), componentDidMount(), and render() lifecycle methods; you will have to meet a few requirements such as: the initial user count should be zero; a message displaying the user count is loading; after the message is loaded, it should show the number of users.
- Update the render function in the UserCountdisplay.js file.
- Create a basic form inside called LoginDisplay.js; import the AjaxLibrary.js here as well.
- Add an onChange event handler to the username in the form and create an eventHandler for the fetchUser function from the Ajaxlibrary.js file.
- Create the Logout button with the required functionality.
- Add the LoginDisplay component to your App component.
- Pass the user prop into the LoginDisplay component by importing the UserDisplay component in the LoginDisplay.
- Update the async function in order to display the loading message.
The final output should look like this:

Figure 4.11: Final output
Note
The solution of this activity can be found on page 623
With this activity, you have successfully created the Messaging App.