React lifecycle methods
Published: 2022-09-02 01:48:12

### What is React lifecycle

A component goes through many different stages from the moment it is created till it is removed. Since our UI is dynamic, to respond to those ever-changing conditions React has given has methods so that we are able to track those changes and therefore respond to them appropriately. In this post, I will cover 4 of them: `render`, `componentDidMount`, `componentDidUpdate` and `shouldComponentUpdate`

---

### render
The job of `render` is to return whatever markup you have written inside of it. Whenever the state of a component changes it will cause the render method to be called again thus the user is able to see the updated content. We use `setState` to change the state of a component which makes React update the component to reflect the changes and thus call the render method again.

#### simple example of render
```javascript
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      counter: 0,
    }
  }

  handleButtonClick = (event) => {
    this.setState({
      counter: this.state.counter + 1,
    });
  }

  render() {
    return (
      <>
        <h1>{`Counter: ${this.state.counter}`}</h1>
        <button onClick={this.handleButtonClick}>Click me</button>
      </>
    );
  }
}
```

The above code will display a button that changes the state of the `counter`, and after every click render will be called again because React detected the change in state. So, we will see the updated `counter` value whenever we click the button thanks to the `render` function being called again.

Few things to note about render function is that: 

- A class component must have a render method, think of this as kind of a contract you make with React you must follow whenever you create a class that extends `React.Component`.
- You must not call `setState` directly inside the render function as React will detect a change which will cause a re-render which will detect `setState` and cause re-render again and so on and on which makes your app go in an infinite loop and crash.

---

### componentDidMount

The `componentDidMount` method is called just once when the component is inserted into the DOM. It is typically used to make API requests and set the initial state or initiailze state which requires DOM nodes.

#### example of componentDidMount
```javascript
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      productsOnSale: []
    }
  }

  getDailyDealsData() {
    // API request to get data about what products are on sale
    this.setState({
      productsOnSale: data, // data from API about what products are on sale
    });
  }

  componentDidMount() {
    this.getDailyDealsData();
  }

  render() {
    return (
      <>
        <h1>Daily Deals</h1>
        <p>{this.state.productsOnSale}</p>
      </>
    );
  }
}
```
Think of the case when you go to the homepage of an e-commerce site like Amazon and you see the daily deals section first. You as a user didn't interact with the website yet but you still see a deals section when the page got loaded. The above code tries to simulate that.


So above example first initializes an empty `productsOnSale` array through the constructor and when the component is inserted into DOM it makes an API request through `getDailyDealsData` function which will update the state of `productsOnSale` and render that data to the browser.


We only need to fetch information about daily deals once at the start when you first load the page and this is a practical example where `componentDidMount` can be used.

---

### componentDidUpdate
The `componentDidUpdate` method gets called whenever the component gets updated, but it is not called for the initial render unlike `componentDidMount` however, it may run more than once. Let's take an example and try to understand it.

#### example of componentDidUpdate
```javascript
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      counter: 0,
    }
  }

  handleButtonClick = (event) => {
    this.setState({
      counter: this.state.counter + 1,
    });
  }
  // ----new function------
  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log("Component updated");
  }

  render() {
    return (
      <>
        <h1>{`Counter: ${this.state.counter}`}</h1>
        <button onClick={this.handleButtonClick}>Click me</button>
        {console.log("render")}
      </>
    );
  }
}
```

The above example is similar to the one in `render` example but here we have defined an extra method `componentDidUpdate` which gets called whenever the component updates. We are changing the value of `counter` whenever the button is clicked hence this is causing the `componentDidUpate` to run and log in to the console "Component updated". 

Also, note that when you load the app for the first time and check the console, there is no "Component updated", it will only run after the initial render.


You might have noticed that `componentDidUpdate` also has some parameters, I will explain their usage below.

#### another componentDidUpdate example
```javascript
componentDidUpdate(prevProps, prevState, snapshot) {
    if (prevState.searchTerm !== this.state.searchTerm) {
      // make API request
      this.searchVideos(this.state.searchTerm);
    }
  }
```
Suppose you are using youtube to search for videos. You searched for "React tutorials" and got the results, then you cleared the input and searched for "React tutorial" again, youtube can opt to not make the same search request again as that would be a waste and thus there will be no update to the component. We can do this like in the example above, we are comparing `prevState` with the current `state` and if there are different search terms, then only make the API request.

---

### shouldComponentUpdate
The `shouldComponentUpdate` dictates whether the component will get updated or not. We can return `true` if we want the component to update otherwise we return `false`. For e.g. I will add a new function to our `render` example.

#### example of shouldComponentUpdate
```javascript
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      counter: 0,
    }
  }

  handleButtonClick = (event) => {
    this.setState({
      counter: this.state.counter + 1,
    });
  }
  // ------new function----
  shouldComponentUpdate(nextProps, nextState) {
    if (nextState.counter % 2 !== 0) {
      console.log("Not updated");
      return false;
    } else {
      return true;
    }
  }
  render() {
    return (
      <>
        <h1>{`Counter: ${this.state.counter}`}</h1>
        <button onClick={this.handleButtonClick}>Click me</button>
      </>
    );
  }
}

```

We just add `shouldComponentUpdate` function and now our functionality of the counter will change as it will now display only "even" values. This happens because we are stopping the re-render from happening if the `counter` is odd. Internally `state` is indeed getting updated and if we click on the button again we will see the value of 2, 4, 6, and so on. We will not see any "odd" numbers even though `setState` method is run, hence render is not called again to show the updated state.

---

Hope you now understand what is lifecycle in react and their methods. If you find any mistakes here kindly let me know in the comments