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.
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.
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.
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 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.
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.
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.
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:
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:
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!
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!