Recently, I started playing around with ReactJS more and one aspect of it I wanted to focus on in this post is its lifecycle methods. Essentially, lifecycle methods are special methods provided by JavaScript frameworks that allow users to “hook” into the views when specific conditions happen (i.e. when the view first renders, when the view gets updated with new data, etc).

You might have noticed in my definition above, I mentioned that lifecycle methods are provided by different JavaScript frameworks / libraries— in order words, they aren’t something unique to ReactJS. In fact, frameworks like AngularJS and BackboneJS / MarionetteJS also have this concept. I won’t go into detail of how they work in other frameworks, but I’ve found that the lifecycle methods in ReactJS are easier to understand because it forces users to really think about state and props, and encourages users to code in a more functional style.

The goal of this post is less a tutorial and more an exploration into the different lifecycle methods in ReactJS. My hope is that exploring these methods will lead to a better understanding of when and how to use them in effective ReactJS code.

Getting Started

I’m breaking down my analysis of lifecycle methods into 2 categories:

When ReactJS components get mounted and unmounted When ReactJS components get updated with new data via state and props

Lifecycle Methods — Mounting / Unmounting

Before diving into this section, let’s get some terminology straight: when talking about lifecycle methods during a ReactJS component’ mounting phase, what we’re specifically concerned with are the methods that get invoked when the component is first initialized and injected into the DOM. Similarly, unmounting deals with the lifecycle methods that get invoked when the component is finally removed from the DOM. What this implies is that the lifecycle methods in this section are invoked only once during the lifetime of the component. The next section will deal with the lifecycle methods that get invoked multiple times during a component’s lifetime.

I’ve gone ahead and prepared a simple gist that highlights the methods that get invoked when a component is first mounted. While I won’t go into detail on how to set up Webpack and BabelJS for a ReactJS project, I’ve found that Pete Hunt’s starter guide is a great no-frills starting point.

Assuming that you’ve got this up-and-running in a HTML file, you should be able to verify in your browser’s console the order in which these lifecycle methods are executed.

getDefaultProps and getInitialState

These two lifecycle methods occur once and happen before the other lifecycle methods, and if we think about what they’re used for, it kind of makes sense. Essentially, these two methods set up the component with its initial data so that the other methods can leverage the data for additional functionality and rendering.

componentWillMount

This lifecycle method happens right before the component is initially rendered. It’s important to note that the component isn’t available in the DOM yet so you shouldn’t do any DOM manipulation within this method. Another subtle implication is that even though the component’s state has been initialized, because the component hasn’t been rendered yet, you can call this.setState within this method and have the component rendered with this updated state.

render

I don’t really consider render a lifecycle method per se, but in the context of this post, I think it makes sense to include it as part of the discussion. Out of the methods in the above gist, it’s the only one that’s invoked multiple times during the component’s lifetime because render isn’t used only during the mounting / umounting phase — its also executed each time a component gets updated with new state or props data.

The absolute most important point about the render method is that it should be pure. This means that it should not perform any actions that have side effects — think of it as a black box where providing the the same state and props data will always output the same result each and every time.

componentDidMount

componentDidMount is the analog to componentWillMount in that it happens right AFTER the component has mounted and rendered initially. At this point, the component is available in the DOM and this is the ideal spot to perform any further DOM manipulation. It’s also the perfect place to perform any set up logic that involves AJAX calls.

componentWillUnmount

Assuming you have a copy of my gist running in your project, if you look closely at your browser’s console, you’ll notice that this lifecycle method isn’t executed. This makes sense because we haven’t run any code that will remove the component from the DOM. But trust me when I say that this lifecycle method gets invoked right BEFORE the component is unmounted / removed from the DOM. This lifecycle method is the perfect spot for any cleanup logic that you might have. The classic example is when a component has some logic that’s been set up with window.setInterval — you’ll want to clear the setInterval within this method so that the logic doesn’t continue executing even after the component has been removed from the DOM.

LifeCycle Methods — Updates to State and Props

The lifecycle methods in the previous section deal with what happens when a ReactJS component is initialized (i.e. mounted) and when it gets removed from the DOM (i.e. unmounted). The ones in this section happen whenever a component has its state and props data updated — which means that unlike the previous ones which get executed once in a component’s lifetime, these get executed many times.

The main difference between this gist and the previous one is that we now have both a ParentComponent and a ChildComponent. However, the focus is really on just the ChildComponent — the ParentComponent is simply here to provide a mechanism to send updated props data to the ChildComponent.

componentWillReceiveProps

This is the first lifecycle method invoked when a component has it’s props data updated. Looking at the ReactJS documentation, we see that this is NOT called during the initial mounting of a component and that its primary purpose is to provide a mechanism for the ChildComponent to update its own state based on the props passed into it from its parent component. This also implies that calling this.setState within this lifecycle method does NOT trigger an additional render for the component.

shouldComponentUpdate

The shouldComponentUpdate lifecycle method acts as a gate by providing a mechanism for users to dictate whether this component should actually re-render based on the new state and props data. As the name suggests, it returns a boolean value and returns true by default. But you can configure it to return false in the scenarios where you don’t want the component to re-render.

It’s important to note that even if the component doesn’t re-render, the state is still maintained by the component — the only thing that happens when this lifecycle method returns false is that the subsequent lifecycle methods (componentWillUpdate, render, and componentDidUpdate) won’t execute for this particular update.

componentWillUpdate / render / componentDidUpdate

These 3 lifecycle methods are very similar to the ones in the previous section. componentWillUpdate is invoked right BEFORE the component is rendered with new data and componentDidUpdate is invoked right AFTER.

Exercise for Readers

Now that we’ve explored a component’s different lifecycle methods, I’ll leave you with a final gist that looks at the sequence in which these lifecycle methods are invoked for every parent and nested child component.

Here’s the browser’s console output when the components in this gist are initially rendered on screen:

(When initially mounted and rendered)

The most interesting aspect of this output is how getDefaultProps for both the ParentComponent and ChildComponent are executed before any other lifecycle methods. My initial expectation was that ChildComponent’s getDefaultProps would be executed later but then the documentation clarifies that getDefaultProps is “invoked once and cached when the class is created.”

Here’s the browser’s console output when the components in this gist are updated with new state and props data:

(I triggered an update by typing “a” into the ParentComponent)

What’s cool to see here is that the ParentComponent’s state changed, it’s render function is triggered which then cascades down to the ChildComponent. All of this is taken care of by ReactJS and it’s one less thing we have to worry about!

Conclusion

Hope you found this post useful in learning about ReactJS’ component lifecycle methods. I’m sure I glossed over a ton of details but hopefully this provides a clear example from which you can continue exploring!