20 March, 2020
React component lifecycle and its methods are an essential part of developing applications in React. While today the approach is being increasingly superseded by React hooks, it’s worth it to take a closer look at how it works, study the relationship between class components and functions, and gain a deeper understanding of DOM manipulation with React. Let’s practice the class-based methods and review their relevance in the light of useEffect’s emergence.
Ever since React came to be, back in 2013, React developers used class components to take full use of the React library (extending from React.Component) in order to manipulate DOM in a React-based app development. How does it work?
React lifecycle method explained
First, let’s take a look at how it’s been done traditionally. As you probably know, each React component has a lifecycle, which consists of three phases:
- Mounting, that is putting inserting elements into the DOM.
- Updating, which involves methods for updating components in the DOM.
- Unmounting, that is removing a component from the DOM.
Each phase has its own methods, which make it easier to perform typical operations on the components. With class-based components, React developers directly extend from the React.Component in order to access the methods.
There is no need to address all of the React component lifecycle methods here. The best source of information on currently supported methods for class components is the official React documentation. Instead, let’s take a closer look at just a couple examples of lifecycle methods. However, before we do, let’s quickly address the topic that is likely on your mind right now.
Class components vs functional components
As you probably know, an alternative way of taking advantage of lifecycle methods is to use hooks. With the release of React 16.8 back in March 2019, it is now possible to create functional components that are not stateless and can use lifecycle methods.
Are hook-enhanced functional components superior to class based ones? Before we get to that, let’s go over the lifecycle phases using the traditional approach.
Mounting in the React component lifecycle
As we mentioned, during the mounting phase of the lifecycle, the class component is inserted into the DOM. A good example would be componentDidMount() – a lifecycle method that runs after the component is mounted and rendered to the DOM. It is great when you want to do an interval function or an asynchronous request. Example:
Updating in the React component lifecycle
The componentDidUpdate() method is called right after the updating happens. This one is called always except for the initial render. That’s a good place to interact with a non-reactive environment. It’s a good idea to make http requests here.
You can call setState() in this method but it is very important to wrap that in some condition to avoid an infinite loop (doesn’t matter if state has the same values or not). If there is no condition, the process goes as follows:
- You call setState() in the componentDidUpdate() method.
- The component is updated.
- componentDidUpdate() is invoked.
- setState() is called again …
Unmounting in the React component lifecycle
componentWillUnmount() is invoked just before the component is removed from the DOM. You should use that to remove event listeners, clear intervals and cancel requests. In other words: all the needed cleanup.
You shouldn’t use setState in that method because the component won’t be rerendered anymore.
React component lifecycle with hooks
You can take advantage of the useEffect hook to achieve the same results as with the componentDidMount, componentDidUpdate and componentWillUnmount methods. useEffect accepts two parameters. The first one is a callback which runs after render, much like in componentDidMount. The second parameter is the effect dependency array. If you want to run it on mount and unmount only, pass an empty array .
To clean up, return the callback in useEffect:
If you want it to behave like componentDidUpdate, put some dependencies into the array or don’t pass the second argument at all.
You can also use useState instead of this.state in class components. Instead of:
You can do that:
As you can, it is possible to use hooks to achieve similar or the same end results.
Class components vs hooks (is there a clear victor?)
Does it mean that the choice is mostly a matter of personal preference? For the most part, that’s the case. If you are more used to functional programming, you will definitely enjoy using hooks. Developers can use functional components without the need to convert them into class components.
Despite the fact that hooks are really popular nowadays, there is nothing wrong with using class components. Everything that you can do with hooks can also be done with class components. Class components aren’t deprecated and are not going to be anytime soon so use them if that style suits you more. It is all about different ways of organizing code and choosing something that is more intuitive for you and your team.