Anatomy of a React Component — Lifecycle Methods 🌳

Jase Pellerin
5 min readNov 13, 2018

--

“pink sakura tree at day time” by Faye Cornish on Unsplash

This is part two of a series on the Anatomy of a React Component, check out the other parts here!

Lifecycle methods are a useful way of reasoning about stateful React components. While other patterns can often allow for cleaner and less coupled code, these methods allow us to execute code at specified times in a component’s life. This can be helpful when learning how components work and can provide insight into when and why they change.

React gives us access to a number of lifecycle hooks. In this article, we’ll go over the methods which are most commonly used (we talked about render last week):

  • constructor
  • componentDidMount
  • componentWillUnmount
  • componentDidUpdate

constructor 🤖

The constructor is likely the most commonly used of React’s lifecycle methods, aside from render. It is also the only one not explicitly added by React, as constructors are available in ES6.

If you are familiar with constructors from other languages, the main difference here is that JavaScript does not have traditional class inheritance but instead mimics that functionality using its underlying prototype-based system (great article on the differences here). In terms of components, however, there isn’t too much to worry about, as your component will extend Component and React will take care of the rest. There are only a couple reasons you would want to use the constructor, however.

The constructor is the first lifecycle method to be called. React uses it only when it creates an instance of a component. This makes it the perfect place for one-time initializations such as initializing state and binding any callbacks that will be used for event handling! React suggests not using the constructor for anything other than these two initialization practices. For any other cases we have…

componentDidMount 🌄

This method is React’s answer to “Where should I put all the random side-effects, data fetching, and DOM-based initialization that my component requires?” This method is typically used for any initialization not covered by the constructor.

componentDidMount is called immediately after a component is mounted (rendered for the first time). This means anything done in here will cause an additional render, which is a good thing. Rendering again allows slower components to do what they need to without blocking the rest of our app.

One caveat to this is calling setState immediately inside componentDidMount, which will tell React not to show the initial state and to wait for the second render before showing. This should typically be avoided, as it can cause performance issues.

A typical use of this method is to initialize event handlers that need DOM references or set up subscriptions. To prevent memory leaks if either of these are used, we need to unsubscribe elsewhere…

componentWillUnmount ☠️

React provides this method as a means for components to clean up after themselves. It gets called right before a component is removed from the DOM and destroyed.

Typically, any event handlers, subscriptions, timers, or other persistent side-effects will be cleaned up in this method. Aside from cleanup, componentWillUnmount can be a useful location for logs or statistics, offer a chance to see how a component is behaving during development, or can trigger some other chain of events (though not typically recommend).

componentDidUpdate ♻️

I saved this one for last, as it can be the most complicated of the commonly used lifecycle methods. This one gets called immediately after a component is updated (due to a change in its props or state), and can be useful for anything that needs to keep in sync with the component as it changes.

One of the most common uses of componentDidUpdate is to update an external piece of the DOM. This is only recommended in an app where React does not have full control over the DOM. In such a case, though, this method will ensure that the entire app is kept in sync.

Another common usage is to perform a side-effect to update a database or service that the component has changed. This can be particularly useful if implementing an app with auto-saving functionality!

One reason componentDidUpdate can be more complicated than its sibling methods is because, unlike the others, it receives parameters. Specifically, it will receive prevProps, prevState, and snapshot.

Using the first two parameters, it is possible to see exactly what triggered the update, which can be useful both for debugging and for triggering different effects depending on what has changed.

The third parameter, snapshot is an interesting one. It will only be provided if you have specified a return value for getSnapshotBeforeUpdate. While uncommon, this can be useful for doing quick calculations on the DOM immediately before an update occurs. The benefit of using this is that React waits until the last possible moment before creating and passing this snapshot, so in a high-intensity app, this can improve performance.

React’s docs say that you can actually trigger setState inside this method, provided that it is inside a conditional. However, this can cause some serious performance issues and is typically indicative of an underlying issue somewhere else in the code.

Example

Here is a basic example of a pair of components which will log their lifecycle methods as they happen:

Best Practices

  • If you aren’t using any lifecycle methods or state, using a functional component can increase performance
  • Be mindful of performance impact of lifecycle methods, especially for components which are created / updated frequently
  • If you add something in componentDidMount, make sure it’s removed in or before componentWillUnmount
  • Experiment — Lifecycle methods let us peek into and tweak components as they’re running, use that to your advantage!

That’s it for lifecycle methods! While they aren’t crucial to the fundamental operation of components, they can be leveraged in many different ways to create complex components. Check out the main article to read more about React and how it works, and follow me to hear about more articles like this.

Let me know which lifecycle method is your favorite / most used in the comments below!

--

--

Jase Pellerin

Intricately-designed mechanism for prolonged computational processing and negligible analytical output