In this article, we’ll dive into the details of the mentioned lifecycle methods, explain how they’re divided, and how they can be used with hooks. Without further ado, let’s jump right in.

What is React?

react (1)

used by giant companies, such as NetflixInstagramor Airbnb. We – as an IT company – also use React in developing products for our clients.

React is one of many JavaScript libraries used to build user interfaces. It is declarative and has promoted declarative programming. But you may ask – what is it exactly?

Well, declarative programming is a style of scaffolding the structure and elements of computer programs that express the logic of a computation without describing its control flow. In React, this means that we never interact with the DOM. The reason for that is that the library operates on a virtual DOM tree and updates the UI only when we change a state. This makes React apps easier to design, develop, and debug. It also improves code readability.

React is also component-based. It means that the structure of the user interface consists of small units connected together. The most important aspects of the library being component-based are modularity and reusability, as you can reuse the units you need for different functionality.

The library is eagerly chosen by developers as a technology for scaffolding web and mobile applications (React Native). It even has more advantages, for example:

  • Performance – React uses a virtual DOM mechanism that is used to avoid updating unnecessary components where no changes have been done, as in the case of conventional web apps.
  • Unidirectional data flow – web apps are easy to debug and you can easily discover the source of the problem.
  • Easy and quick to learn.
  • Small learning curve.

What are React Components?

react-components-1536x1024

In a React application, the basic structure item is a component. Developers use them to split the code and isolate parts of the application.

We can divide components into two main groups:

  • Class Components – can manage the component lifecycle and state management by default.
  • Functional Components – simple, quick to create, and stateless by default.

Each React class component has a lifecycle, which essentially is a component’s state. The lifecycle logic was defined and provided by React (class component inherits from React.Component) and adds support ability to handle events in each component lifecycle stage. There are different phases to the lifecycle – or in other words – three stages of a component’s life: mounting, updating, and unmounting. Flow is simple and a little bit similar to the natural life cycle.

  • Mounting – birth of the component.
  • Update – growth of the component.
  • Unmount – death of the component.

Now, what is a component’s lifecycle? As you can see above – it’s simply a life of a component. First, it gets mounted on the DOM (the birth stage). Secondly, it gets updated over time, which essentially means its growth. And finally, last but not least, it gets unmounted, which is the end of the component.

Each class component in each lifecycle stage has built-in methods available which give developers a way to react when the component evolves. The component evolves when props or state change. The situation is a little bit different when using hooks in functional components, but it will be described later.

Stage 1: Mounting

Mounting is the first stage in the React component lifecycle. It means that a component was set up onto the DOM tree.

There are five methods that could be classified in this stage. They’re represented in the correct order below:

  1. constructor()
    The first method is the constructor method which is called before the component is mounted. You can implement this method at the top of the component structure. Constructor might be used for initializing local component state and binding event handler methods. Now, onto the other lifecycle methods.
  2. componentWillMount()
    Invoked just before the render method. Usually used to set the component state to avoid additional re-renders. Might not contain any side-effects handlers. From React version 17 it became legacy and will be discontinued in the future. This method has been replaced by the getDerivedStateFromProps method.
  3. static getDerivedStateFromProps(props, state)
    This method is called right before render() and it is the natural place to set the state based on initial props. It takes props and state as arguments and returns an object with changes to the state.
  4. render()
    Contains JSX code which should be rendered when the component is mounted. Unlike the other methods described above, render() is the only required method and does not depend on the user. React calls this method automatically when some prop or state value changes. This is a result of a default React component principle that says: always re-render.
  5. componentDidMount()
    This method is invoked after the first render component in the DOM. This is a good place to operate on the DOM tree or set up any subscriptions. It might also be used to set a state. It will trigger extra rendering but the screen will not be refreshed by the browser just yet. As a result, intermediate state values invoked in the render method will not render in the browser.

Stage 2: Updating

After the mounting phase, the next lifecycle method is updating. As long as the component remains mounted, it may be updated. Without updates, the component would remain the same as in the initial phase.

An update can be caused by changes to props or state. There are many methods to monitor and react to updates. Methods are called in the following order while the component re-renders:

  1. shouldComponentUpdate(nextProps, nextState)
    This method is used to avoid unnecessary component re-renders. By default, the component will re-render on every prop or state change. The developer may determine the condition when the component should be re-rendered. This method is invoked when new props or states are being received. There are some exceptions to the rule, for example, when it is the first component rendered or when forceUpdate() is used.
  2. static getDerivedStateFromProps(props, state)
    Same as in the previous stage.
  3. render()
    Same as in the previous stage. The only method that is required.
  4. getSnapshotBeforeUpdate(prevProps, prevState)
    The method is called right before the component re-renders by using the render method. Commonly used to get some data needed after the next render, for example, to get data about scroll position. The returned value will be passed to componentDidMount method as 3rd parameter.
  5. componentDidUpdate(prevProps, prevState, snapshot)
    Method componentDidUpdate is called right after render(), excluding the initial render call. Used to operate on a DOM tree or to handle certain side-effects when any of passed arguments change.

Stage 3: Unmounting

Unmounting is the last stage of a component’s life.

  1. componentWillUnmount()
    This method is invoked immediately before component destruction. Used to clean up, remove listeners, subscriptions, abort pending requests, etc.

React Component Lifecycle Using Hooks

Compared to the React update with hooks that were introduced in version 16.8, class components have less popularity. Beforehand, only a class component could persist in a state.

Hooks give possibilities to manage state in functional components as well. Most new applications use only functional components with hooks instead of classes.

What does a component lifecycle look like when using functional components with hooks?

React creators simplified that a little bit compared to a class-based solution. The methods componentDidMountcomponentDidUpdatecomponentWillUnmount were included in one place – the useEffect hook.

The structure of the useEffect hook is simple.

useEffect(() => {
  // code runs when dependencies changed
  return () => {
    // code runs just before dependencies change
  }
}, [dependencies])

Let’s try to write the same code using a class component and a functional component with hooks:

componentDidMount() {
    this.subscription = props.data.subscribe(this.handleDataChange);
}

componentDidUpdate(prevProps) {
  if(prevProps.data !== props.data) {
      this.subscription.unsubscribe();
      this.subscription - props.data.subscribe(this.handleDataChange);
  }
}

componentWillUnmount() {
    this.subscription.unsubscribe();
}

And now let’s do the same thing but with the help of a functional component with hooks:

useEffect(() => {
    const subscription = props.data.subscribe(handleDataChange);

    return () => {
      subscription.unsubscribe(handleDataChange)
    }
}, [props.data])

Both code fragments do exactly the same thing. The first one is a little bit cleaner, but so often the code in componentDidMount and componentDidUpdate is partially duplicated. With hooks, the developer has to remember how it works exactly. The example with hooks shown above runs the code inside – on the component mount – and when one of the params in dependency list changes. The developer may contain all operations in one place due to the useEffect method of working.

shouldComponentUpdate – hooks implementation:

As you can see, this method is not available with functional components. Fortunately, React creators found a solution for that:

class MyComponent extends React.Component {
    shouldComponentUpdate(nextProps) {
        return nextProps.value !== this.props.value;
    }
    render() {
        return (
            <div>{this.props.value}</div>
        );
    }
}

React.memo is a HOC (Higher-Order Component). If previous props are the same as the current ones, React skips re-rendering this component and uses the previous render value instead. It does shallow props comparison, which essentially is a comparison of props. If it is needed, a function that does custom comparison could be passed as the second argument.

React Lifecycle Methods: The Conclusions

What we need to remember is that components in React create trees. The same component can be a child and also a parent to different components. They can communicate with each other, get data, persist them, and pass it to another component. This gives React the ability to utilize the functional programming paradigm and allows developers to build complex applications. In fact, the entire component lifecycle can be managed by using dedicated methods or by hooks.

From a certain version, when React introduced hooks, most new features were created towards hook growth. Looking to the future, the React creators plan to develop more features related to functional programming, which we can read about in the announcement of the next version of React 18.

Our Office

Massive Pixel Creation Sp. z o.o.

Jesionowa 22, 40-158

Katowice, Poland

+48 516 711 852

Tax ID: PL9542832894

Company
Blog
Follow us

Web Development
Ideation & Evaluation
Mobile Development
Product Type
Our Awards
Clutch Reviews-2
Techreviewer
Design Rush
Word Press Development
Good Firms
App Futura

Massive Pixel Creation 2024 © All Rights Reserved Privacy Policy