2

I am reviewing some React Js basics and I need some clarifications about the use of the constructor method within a react class based component. My normal practice is to declare a class based component and define state without using the constructor, like so:

import React, { Component } from 'react';

export class Testing extends Component {
  state = {
    example: "Hello World!!!"
  }

  render() {
    return <div>
      {this.state.example}
    </div>;
  }
}

export default Testing;

Since state is so easy to use without the (seemingly) pointless constructor, I began asking myself what the constructor was for. Just to clarify what I mean by the constructor, it is when you declare state like this instead of the above example:

constructor(props) {
  super(props)

  this.state = {
    example: "Hello World!!!"
  }
}

I found the suggestion in the react documentation that it is best practice to utilize the constructor, but it did not say why. After a little searching, I found a source that suggested that the constructor give you access to the props. I tested this and do see how the constructor gives access to props; however, the class can access props WITHOUT using the constructor, simply by stating this.props.myTest. I tested this as well by defining props in a parent component and drilling them down to the child component. I was able to access the props just fine with the this.props.myTest statement, no constructor necessary. So my question is, "What specifically does the constructor do, and when is it necessary (or is it ever necessary)?"

Luke Sharon
  • 140
  • 1
  • 7
  • 22
  • Doesn't react automatically add a constructor for class components? – evolutionxbox Jan 23 '22 at 00:02
  • 4
    It is the same. When you write it without a constructor, babel handles it for you and creates a constructor for you when you build the app. Kinda like syntax sugar, with less code to write for developers. – oakar Jan 23 '22 at 00:03
  • @evolutionxbox Not react. All JS `class`es [do get a default constructor](https://stackoverflow.com/a/48657525/1048572) – Bergi Jan 23 '22 at 00:06
  • @oakar interesting...so specifically defining a constructor is entirely unnecessary? Definitely good to know that it is a behind the scenes thing, so I guess there is no use case when I should specifically define it? I'm mostly curious because defining a constructor seems to make the code a little messy and confusing, especially if it isn't needed. – Luke Sharon Jan 23 '22 at 00:07
  • 2
    @LukeSharon Iff you use class fields to initialise all your properties, and if there's nothing else the constructor does, yes you don't need to define it. – Bergi Jan 23 '22 at 00:09
  • 1
    If you use functions without arrow functions in your class, you need to use the constructor to bind your functions so it is not entirely unnecessary. see first code snippet as an example: https://www.freecodecamp.org/news/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb/ – oakar Jan 23 '22 at 00:59
  • 1
    _"I found the suggestion in the react documentation"_: Can you link that documentation ? – kca Jan 23 '22 at 09:26

1 Answers1

2

"when is the constructor necessary ?":

The constructor is not necessary, if you don't need it.

You might need a constructor e.g. if you need to bind a method to the class instance (so that this keeps pointing to the class instance if you pass the function over to some other execution context):

export class Testing extends Component {
  constructor( props ) {
    super( props );
    this.myMethod = this.myMethod.bind( this );
  }
  
  myMethod(){
    console.log( this.props ); 
  }

  render() {
    return <button onClick={ this.myMethod }>
      click
    </button>;
  }
}

"What specifically does the constructor do" ?

A constructor "creates the instance" in javascript. So without a constructor, there would be no instance. But also there is inherently always a constructor, even if you don't define one specifically.

You can define a constructor to overwrite the default constructor or to add some extra logic to be run additionally to the super-constructor.

Accessing this.props in React

In javascript you could not access this.props without calling super(props).

Note that the constructor argument props and the instance property this.props are different "things". Let's rename the constructor argument for now, to make it more obvious:

class SuperClass {
  constructor( constructorArguments ) {
    this.props = constructorArguments;
  }
}

class DerivedClass extends SuperClass {
  constructor( props ) {
    super();                   // <-- call the SuperClass constructor
  }
  method(){
    console.log( this.props ); // <-- this.props is obviously never defined
  }
}

const instance = new DerivedClass('some props');
instance.method();

But React "takes measures" to assign this.props anyway, even when super(props) was never called.

But that happens later (after the constructor is done), so you are able to access this.props in other methods later, but not inside the constructor:

export class Testing extends Component {

  constructor( constructorArguments ) {
    super();                   // <-- super() is called without arguments
    console.log( this.props ); // <-- this.props is undefined
  }

  render() {
    console.log( this.props ); // <-- React sorted it out, now this.props is available 
    return null;
  }
}

If you pass the constructor arguments to the super class constructor, then you can access this.props inside the constructor:

constructor( constructorArguments ) {
  super( constructorArguments );   // <-- super() is called with arguments
  console.log( this.props );       // <-- this.props is available
}

React recommends to call super(props) anyway, to avoid introducing bugs with later changes. I might add that it is very little extra code that doesn't do any harm.

Defining the state

class fields were not always available, so you had to define the state inside the constructor, as the React example shows (like this.state = { value: 'value' }).

I personally think that it is probably ok now to use the class fields, but I always tend to follow the official documentation, even if it might be outdated. There still might be implications which I am not aware of.

See also: is-it-better-to-define-state-in-constructor-or-using-property-initializers

kca
  • 4,856
  • 1
  • 20
  • 41