Home

Component Lifestyle Methods

the component lifecycle has three high-level parts:-

Mounting
when the component is being initialized and put into the DOM for the first time.

Updating
when the component updates as a result of changed state or changed props.

Unmounting
when the component is being removed from the DOM.

The constructor runs in the Mounting phase.
While the render() can run in the mounting and/or the Updating phase.

Therefore it could be best to run some functions, for example the setInterval() function, AFTER the render().
NOTE
For things like setInterval() the render() isn’t a good location.
For one, it executes during the mounting phase and the updating phase—too often for us.
It’s also generally a bad idea to set up any kind of side-effect like this in render(), as it can create subtle bugs in the future.

the constructor() is also not a great location.
It does only execute during the mounting phase, so that’s good, but you should generally avoid side-effects like this in constructors because it violates something called the Single Responsibility Principle.
In short, it’s not a constructor’s responsibility to start side-effects.


During the Mounting Phase there is a FINAL method (after constructor() and render()) - it is known as the componentDidMount method.
This is where you run statements that requires that the component is already placed in the DOM.

During the Unmounting Phase there is a FINAL method - it is known as the componentWillUnMount method,
It runs just BEFORE the class it is in gets removed/cleared.

The componentDidUpdate method runs when an update occurs (after a render()).
This is called after the update has been rendered in the DOM
See w3schools document on React Lifestyle

componentDidMount() method

This method is called AFTER the render method is completed.
Which means that, for functions like, for example the setInterval() function, it will only start once the render() has been dealt with.

A Code Example...

import React from 'react';
import ReactDOM from 'react-dom';

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }

  render() {
    return (
        <div>
                {this.state.date.toLocaleTimeString()}
        </div>
  }

                componentDidMount() {
        const oneSecond = 1000;
        setInterval(() => {
          this.setState({ date: new Date() });
        }, oneSecond);
                }

}

ReactDOM.render(<Clock />, document.getElementById('app'));
The above example code will just print the TIME on screen using (in render())
{this.state.date.toLocaleTimeString()}

To do this it sets, in the constructor(), the property date
and as it is set as a this.state.date property then whenever it's value changes the screen will get re-rendered.

The value of this.state.date changes inside the componentDidMount() method - it uses this.setState to change the time stored in this.state.date every one second.

For more on setInterval() you can Click Here

Top

componentWillUnmount()

componentWillUnmount() is the last function to be called immediately before the component is removed from the DOM.
It is generally used to perform clean-up for any DOM-elements or timers created in componentWillMount().

Using this Clock class scenario...
...We never told the interval to stop, so it’ll keep running that function forever (or at least, until the user leaves/refreshes the page).

When the component is unmounted (in other words, removed from the page), that timer will keep on ticking, trying to update the state of a component that’s effectively gone.

This means your users will have some JavaScript code running unnecessarily, which will hurt the performance of the app.

React will log a warning that looks something like this:

Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.


If you do not stop the setInterval() then the clock gets mounted and unmounted hundreds of times—eventually, this will cause your page to become sluggish because of all of the unnecessary work.
You’ll also see warnings in your browser console.
Even worse, this can lead to subtle, annoying bugs.

components can have lots of other side-effects:
loading external data with AJAX, doing manual tweaking of the DOM, setting a global value, and more.
We try to limit our side-effects, but it’s difficult to build an interesting app with truly zero side-effects.


...JavaScript gives us the clearInterval() function to reset the setInterval().

setInterval() can return an ID, which you can then pass into clearInterval() to clear it.

Example...

const oneSecond = 1000;
this.intervalID = setInterval(() => {
  this.setState({ date: new Date() });
}, oneSecond);
 
// Some time later...
clearInterval(this.intervalID);

ComponentWillUnmount() Example

import React from 'react';

export class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }
  render() {
    return (
        <div>{this.state.date.toLocaleTimeString()}</div>
    )
  }
  componentDidMount() {
    const oneSecond = 1000;
                this.intervalID = setInterval(() => {
      this.setState({ date: new Date() });
    }, oneSecond);
  }

                componentWillUnmount() {
        clearInterval(this.intervalID);
                }
}
The above example creates a class (Clock) that gets exported
And, therefore will be imported, in another file and ran from there.


While the componentWillMount() gets run after the render() completes the componentWillUnmount() runs just before the class it is in gets removed/cleared.

In the above example this.intervalID gets set (in the componentWillMount() method and then is read in when clearInterval() is run.

Top

componentWillUpdate()

The componentDidUpdate method runs when an update occurs (eg this.setState() was used) and a render() occurred.

Using our clock example (shown to the right) we now have...

a function called startInterval() which sets the interval timer (setInterval()) and is called from both the componentDidMount() and componentDidUpdate() methods.
This was done so we do not duplicate code

startInterval() checks if the precise time is required to be displayed (this.props.isPrecise will be TRUE) and if so the interval is set to be 10 times a second.
If it was FALSE it is set to be once a second.

In the render() method it also checks the this.props.isPrecise value and if it is TRUE it will display a longer time, with 100th's of a second...
2021-08-24T12:38:57.546Z
and if it was FALSE it displays as
12:38:57 PM

Although the render() method displays the time it would not update the value as it needs the timer to be set (startInterval()) which tells it to keep updating the time which also makes it re-render the screen.

The componentWillMount() method runs when the page first mounts (displays) so we have called the startInterval() function in here.
That way the interval timer starts the first time the page is displayed.

If/when the Clock class is stopped from running then the componentWillUnmount() method runs so we had to tell the program to STOP the interval timer running.
clearInterval() stops the interval timer.

Finally we have a method called componentDidUpdate which runs whenever the render() method runs.
Here we need to check if the clock has to be re-displayed or not.
If this.props.isPrecise = TRUE then show the longer time Nd if it was FALSE then show the shorter time.
But because we do not want to redisplay it AND start a new interval timer running we needed to check if this.props.isPrecise had been changed.
If was unchanged then DO NOTHING.
But if it has changed then we have to start a new interval timer running by calling startInterval() again (Note, the componentWillUnmount method will have already stopped the old timer running).

componentWillUpdate() example

import React from 'react';

export class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }

                startInterval() {
    let delay = 1000;
    if (this.props.isPrecise) {
      delay = 100;
    }
    this.intervalID = setInterval(() => {
      this.setState({ date: new Date() });
    }, delay);
  }

  render() {
    return (
        <div>
            {this.props.isPrecise
              ? this.state.date.toISOString()
              : this.state.date.toLocaleTimeString()}
      </div>
    );
  }
  componentDidMount() {
                this.startInterval();
  }
  
  componentWillUnmount() {
    clearInterval(this.intervalID);
  }

  componentDidUpdate(prevProps) {
    if (this.props.isPrecise === prevProps.isPrecise) {
      return;
    }
                this.startInterval();
  }
}


                The web page that uses this class had two buttons on it 
plus the time being displayed.


12:38:57 pm


The [Toggle Clock On/Off] button removed the clock & stopped it running.
The [Toggle Precise Mode Clock] button stopped the clock and displayed a new one in the new (longer) format (or, if it was already the longer format, displayed it in the short format).
but here I am not showing a working clock (no interval timer)

Top

Component Lifestyle Review

Review
There are three major phases of a component’s lifecycle:-

Mounting
when the component is being initialized and put into the DOM for the first time.
The constructor(), render(), and componentDidMount() methods are called during this phase.

Updating
when the component updates as a result of changed state or changed props.
The render() and componentDidUpdate() are called during this phase.

Unmounting
when the component is being removed from the DOM.
The componentWillUnmount() is called here, which is a good time to clean things up.


A picture representing the common lifestyles can be found Here

Note
If you click on the link you can then tick the 'Show less common lifecycles' option to see more methods (that are less used).

Top