The best way to use class component In ReactJS

Firstly, let's discuss what class component is all about before the code samples. Before React 16.8, Class component is the only way to track state and lifecycle on a React component. Function component was considered "state-less". You may be wondering what state-less means in React. Stateless components, by contrast, have no state, and also we can say that a "stateful" component is a component that holds some state in React.

But now, with the addition of Hooks, Function components are now almost equivalent to Class components. The differences are so minor that you will probably never need to use a Class component in React. Not withstanding, even though Function components are preferred, there are no current plans on removing Class components from React.

Note that when creating a React component, the component's name must start with an upper case letter. And the component has to include the extends React.Component statement, this statement creates an inheritance to React.Component, and gives your component access to React.Component's functions.

The component also requires a render() method, this method returns HTML.

Let give code sample:

class House extends React.Component {
  render() {
    return <h2>Hi, I am a House!</h2>;
  }
}

You can see that our React application has a component called House, which returns a <h2> element. Now to use this component in your application, use similar syntax as normal HTML: <Car />

You can now display the House component in the "root" element

Example:

ReactDOM.render(<House />, document.getElementById('root'));

You have to add a constructor() to your component, If there is a constructor() function in your component, this function will be called when the component gets initiated. The constructor function is where you initiate the component's properties.

Note: In React, component properties should be kept in an object called state. The constructor function is also where you honor the inheritance of the parent component by including the super() statement, which executes the parent component's constructor function, and your component has access to all the functions of the parent component (React.Component).

Example of how to add a constructor to a class component:

class House extends React.Component {
  constructor() {
    super();
    this.state = {location: "Quebec"};
  }
  render() {
    return <h2>I am a House!</h2>;
  }
}

Now use the location property in the render() function:

class House extends React.Component {
  constructor() {
    super();
    this.state = {location: "Quebec"};
  }
  render() {
    return <h2>I am a {this.state.location} House!</h2>;
  }
}

There is another way of handling component properties is by using props. Props are like function arguments, and you send them into the component as attributes.

You can use an attribute to pass a location to the House component, and use it in the render() function:

class House extends React.Component {
  render() {
    return <h2>I am a {this.props.location} House!</h2>;
  }
}

ReactDOM.render(<House location="Quebec"/>, document.getElementById('root'));

Note: If your component has a constructor function, the props should always be passed to the constructor and also to the React.Component via the super() method.

Example:

class House extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return <h2>I am a {this.props.location}!</h2>;
  }
}

ReactDOM.render(<House location="Quebec"/>, document.getElementById('root'));

You can also refer to components inside other components:

class House extends React.Component {
  render() {
    return <h2>I am a House!</h2>;
  }
}

class Location extends React.Component {
  render() {
    return (
      <div>
      <h1>Where is the house located at Quebec?</h1>
      <Car />
      </div>
    );
  }
}

ReactDOM.render(<Location />, document.getElementById('root'));

You might have noticed that we used state earlier in the component constructor section. The state object is where you store property values that belongs to the component. When the state object changes, the component re-renders.

Now, let's create another state object containing some properties:

class House extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      location: "Quebec",
      street: "Rue du Cul-de-Sac",
      color: "blue",
      year: 2022
    };
  }
  render() {
    return (
      <div>
        <h1>My New House</h1>
      </div>
    );
  }
}

You can refer to the state object anywhere in the component by using the this.state.propertyname syntax:

class House extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      location: "Quebec",
      street: "Rue du Cul-de-Sac",
      color: "blue",
      year: 2022
    };
  }
  render() {
    return (
      <div>
        <h1>My {this.state.location}</h1>
        <p>
          It is located at {this.state.street}.
          It has {this.state.color} color.
          Built in the year {this.state.year}.
        </p>
      </div>
    );
  }
}

Now, to change a value in the state object, use the this.setState() method.

Note: When a value in the state object changes, the component will re-render, meaning that the output will change according to the new value(s).

Code Sample:

class House extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      location: "Quebec",
      street: "Rue du Cul-de-Sac",
      color: "blue",
      year: 2022
    };
  }
  changeYear = () => {
    this.setState({year: 2021});
  }
  render() {
    return (
      <div>
        <h1>My {this.state.location}</h1>
        <p>
          It is located at {this.state.street}.
          It has {this.state.color} color.
          Built in the year {this.state.year}
        </p>
        <button
          type="button"
          onClick={this.changeYear}
        >Change year</button>
      </div>
    );
  }
}

Make sure you always use the setState() method to change the state object, it will ensure that the component knows it's been updated and calls the render() method (and all the other lifecycle methods).

Lifecycle of Components

Each component in React has a lifecycle which you can monitor and manipulate during its three main phases.

The three phases are: Mounting, Updating, and Unmounting.

Let's explain this phases one after the other:

Mounting:

Mounting means putting elements into the DOM.

React has four built-in methods that gets called, in this order, when mounting a component which are:

  • constructor()

  • getDerivedStateFromProps()

  • render()

  • componentDidMount()

Among others built-in methods, the render() method is required and will always be called, the others are optional and will be called if you define them.

Constructor method:

For the constructor method, the constructor() method is called before anything else, when the component is initiated, and it is the natural place to set up the initial state and other initial values.

The constructor() method is called with the props, as arguments, and you should always start by calling the super(props) before anything else, this will initiate the parent's constructor method and allows the component to inherit methods from its parent (React.Component).

Code Sample:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "blue"};
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

getDerivedStateFromProps method:

The getDerivedStateFromProps() method is called right before rendering the element(s) in the DOM. This is the natural place to set the state object based on the initial props. It takes state as an argument, and returns an object with changes to the state. The example below starts with the favorite color being "blue", but the getDerivedStateFromProps() method updates the favorite color based on the favcol attribute.

Code Sample:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "blue"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header favcol="green"/>, document.getElementById('root'));

render method:

The render() method is required, and is the method that actually outputs the HTML to the DOM.

Code Sample:

class Header extends React.Component {
  render() {
    return (
      <h1>This is the content of the Header component</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

componentDidMount method:

The componentDidMount() method is called after the component is rendered. This is where you run statements that requires that the component is already placed in the DOM.

Code Sample:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "blue"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "green"})
    }, 1000)
  }
  render() {
    return (
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Updating:

Let's talk about the next phase of the lifecycle of components which is updating:

This lifecycle happens to be used when a component is updated.

A component is updated whenever there is a change in the component's state or props.

React has five built-in methods that gets called, in this order, when a component is updated, which are:

  • getDerivedStateFromProps()

  • shouldComponentUpdate()

  • render()

  • getSnapshotBeforeUpdate()

  • componentDidUpdate()

The render() method is required and will always be called, the others are optional and will be called if you define them.

getDerivedStateFromProps method:

Also at updates the getDerivedStateFromProps method is called. This is the first method that is called when a component gets updated. This is still the natural place to set the state object based on the initial props. The example below has a button that changes the favorite color to blue, but since the getDerivedStateFromProps() method is called, which updates the state with the color from the favcol attribute, the favorite color is still rendered as green:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  static getDerivedStateFromProps(props, state) {
    return {favoritecolor: props.favcol };
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header favcol="green"/>, document.getElementById('root'));

shouldComponentUpdate method

In the shouldComponentUpdate() method you can return a Boolean value that specifies whether React should continue with the rendering or not.

The default value is true.

The example below shows what happens when the shouldComponentUpdate() method returns false:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return false;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Same example as above, but this time the shouldComponentUpdate() method returns true instead:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  shouldComponentUpdate() {
    return true;
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

render method

The render() method is of course called when a component gets updated, it has to re-render the HTML to the DOM, with the new changes.

The example below has a button that changes the favorite color to blue:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "red"};
  }
  changeColor = () => {
    this.setState({favoritecolor: "blue"});
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <button type="button" onClick={this.changeColor}>Change color</button>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

getSnapshotBeforeUpdate method

The getSnapshotBeforeUpdate() method you have access to the props and state before the update, meaning that even after the update, you can check what the values were before the update.

Note: If the getSnapshotBeforeUpdate() method is present, you should also include the componentDidUpdate() method, otherwise you will get an error.

The example below might seem complicated, but all it does is this:

When the component is mounting it is rendered with the favorite color "blue".

When the component has been mounted, a timer changes the state, and after one second, the favorite color becomes "green".

This action triggers the update phase, and since this component has a getSnapshotBeforeUpdate() method, this method is executed, and writes a message to the empty DIV1 element.

Then the componentDidUpdate() method is executed and writes a message in the empty DIV2 element:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "blue"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "green"})
    }, 1000)
  }
  getSnapshotBeforeUpdate(prevProps, prevState) {
    document.getElementById("div1").innerHTML =
    "Before the update, the favorite was " + prevState.favoritecolor;
  }
  componentDidUpdate() {
    document.getElementById("div2").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
        <h1>My Favorite Color is {this.state.favoritecolor}</h1>
        <div id="div1"></div>
        <div id="div2"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

componentDidUpdate method:

The componentDidUpdate method is called after the component is updated in the DOM.

The example below might seem complicated, but all it does is this:

When the component is mounting it is rendered with the favorite color "blue".

When the component has been mounted, a timer changes the state, and the color becomes "green".

This action triggers the update phase, and since this component has a componentDidUpdate method, this method is executed and writes a message in the empty DIV element:

class Header extends React.Component {
  constructor(props) {
    super(props);
    this.state = {favoritecolor: "blue"};
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({favoritecolor: "green"})
    }, 1000)
  }
  componentDidUpdate() {
    document.getElementById("mydiv").innerHTML =
    "The updated favorite is " + this.state.favoritecolor;
  }
  render() {
    return (
      <div>
      <h1>My Favorite Color is {this.state.favoritecolor}</h1>
      <div id="mydiv"></div>
      </div>
    );
  }
}

ReactDOM.render(<Header />, document.getElementById('root'));

Unmounting:

This lifecycle is when a component is removed from the DOM, or unmounting as React likes to call it.

React has only one built-in method that gets called when a component is unmounted which is:

  • componentWillUnmount()

componentWillUnmount method:

componentWillUnmount method is called when the component is about to be removed from the DOM.

Code Sample:

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = {show: true};
  }
  delHeader = () => {
    this.setState({show: false});
  }
  render() {
    let myheader;
    if (this.state.show) {
      myheader = <Child />;
    };
    return (
      <div>
      {myheader}
      <button type="button" onClick={this.delHeader}>Delete Header</button>
      </div>
    );
  }
}

class Child extends React.Component {
  componentWillUnmount() {
    alert("The component named Header is about to be unmounted.");
  }
  render() {
    return (
      <h1>Hello World!</h1>
    );
  }
}

ReactDOM.render(<Container />, document.getElementById('root'));

Thanks for reading to the end, I believe you gain more knowledge.

Happy Coding!

Code once think twice...

Did you find this article valuable?

Support Saint Vandora by becoming a sponsor. Any amount is appreciated!