React Component lifecycle methods, part I

Yassi Mortensen
4 min readMar 18, 2018

--

React comes with a lot of built-in methods and tools that are called during the lifecycle of a component. These methods allow developers easy ways to update the UI and application state. Knowing when to use each of them, and each of their caveats, is crucial to properly understanding how to build with React.

The above is the life-cycle of a React component, from inception (pre-mounting) to death (unmounting).

The most attractive part of React is the concept of splitting complicated UI’s into smaller, tiny bits. Not only can we organize and compartmentalize React apps, but we can also make each component completely customizable. If we use lifecycle methods correctly, we can control what happens when each little section of our app renders, updates, considers re-rendering, and then disappears completely.

I will be going over all of React’s lifecycle methods eventually. But for this blog, I’m going to focus on the constructor, componentWillMount, and componentDidMount functions.

constructor

This is a special function that will get called whenever a new object is created — so, essentially, it’s a basic part of Object Oriented Programming that’s common across multiple languages. The constructor is also a convenient place to define the state of your component.

import React from 'react';class Hello extends React.Component {
constructor(){
super();
this.state = {
hello: "Hello",
world: "World!
}
}
render(){
return(<p>{this.state.hello} {this.state.world}</p>)
}
}
export default Hello

Notice that within our constructor function we call another special function called super(). This is important in cases where our class extends any other class that also has a defined constructor. Calling super() will therefore call the constructor of the parent class and allow it to initialize itself. Only after we call super() in our constructor can we have access to this.props. Very, very important!

Also keep in mind that the constructor is the only place where you can define/set the state of the component with this.state. In all other instances of state changes, it’s encouraged to use this.setState . While it is technically possible to alter state by writing to this.state directly, it will not lead to the component re-rendering with new data, and generally lead to state inconsistency and possible async issues.

componentWillMount

So here’s the thing… nobody likes this method. Which is why it was depreciated in early 2018 in React v16.3. Still, it’s good practice to go over why this method hasn’t worked well in the past.

The thing about componentWillMount is that when it is called, no component exists yet to actually do anything with. So, you can’t technically do anything involving the DOM. There is also very little that you can do here that you can’t already do in the constructor. Also, nothing has changed since your component’s constructor was called, so… we’re kind of in JSX limbo at this point. Your component is in a default position at the moment, and almost everything that should be taken care of for setup has already been dealt with by the constructor and the rest of your component code.

However, there is an exception to this. Any setup that can only be done at runtime (connecting to external API’s, setup for Firebase launch, etc) needs to be prepared as your app is first mounting. Keep in mind, though, that any such configuration should be done at the highest level component on your app (the root component). So, unless you are in your root component, don’t use componentWillMount!

componentDidMount

This is arguably the most favorite and highly-used lifecycle method in any React app that you can find on the market. This method is called after your component is created and mounted in the DOM, ready to be used.

This function will be called only once in the whole lifecycle of a given component, and will only be called after the component has rendered properly. Since this function is never called more than once, it is the perfect place for performing any side-effect causing operations (such as AJAX requests).

At this point, you are ready to load your data and do all of the setup that you couldn’t do without the DOM. However, try to avoid calling this.setState() directly in componentDidMount. This is because calling this.setState() will result in a re-render once state has been successfully changed, which can cause some async issues if other components are also updating their states in the same manner. To avoid this, I generally like calling a secondary function with my fetched data that handles state changes instead.

import React from 'react';class Hello extends React.Component {
constructor(){
super();
this.state = {
hello: "Hello",
world: "World!,
products: []
}
}
componentDidMount(){
this.getProducts()
}
getProducts = () => {
fetch(API_LINK)
.then(res => res.json())
.then(res =>
this.setState({products:[...this.state.products, ...res]}))
}
render(){
return(INSERT DOM MARKUP HERE)
}
}
export default Hello

That’s all for now, everyone. We’ve covered all of the built in React methods that handle component creation, setup, and mounting onto the DOM. In my next blog, we’ll dive even further into React lifecycle methods that involve changes in props.

--

--