Search code examples
javascriptreactjsecmascript-6ecmascript-5

Difference between ES5 and ES6 constructors in React.js


In React's source code, the prototype function has a signature with three parameters:

function Component(props, context, updater) {

But everytime I see somebody extends React.Component using modern ES6 features, they declare constructor with only props as follows:

constructor(props)

What is the difference between a prototype function and constructor literal? And where do the rest two arguments go?


Solution

  • You can obviously use all of the three params provided in the Component. But in general, only in an advanced case we use props, not every time. Similarly, you can use others.

    Here's an example with context api:

    ES6 class component

    class ContextConsumer extends React.Component {
      /* 
         contexTypes is a required static property to declare 
         what you want from the context
      */
      static contextTypes = {
          currentUser: React.PropTypes.object
      };
      render() {
        const {currentUser} = this.context;
        return <div>{currentUser.name}</div>;
      }
    }
    

    ES6 class component with an overwritten constructor

    class ContextConsumer extends React.Component {
      static contextTypes = {
          currentUser: React.PropTypes.object
      };
      constructor(props, context) {
        super(props, context);
        ...
      }
      render() {
        const {currentUser} = this.context;
        return <div>{currentUser.name}</div>;
      }
    }
    

    Example taken from this blog. I will suggest you to look into the blog to be more familiar with it.

    Another param is updater which you may have used this.forceUpdate() and doing so invoke the updater. But the fact, we do not use updater directly in normal case. Though, I have not faced such case to use the updater inside the constructor. You might be able to figure out if you face some advanced case.


    To be more frank and to use react with clever, I never even try to use props as far as possible. They are just provided for us so that we can utilize in lifecycle hooks when needed.


    Okay, let me explain it a little bit with react code:

    function Component(props, context, updater) {
      this.props = props;
      this.context = context;
      // If a component has string refs, we will assign a different object later.
      this.refs = emptyObject;
      // We initialize the default updater but the real one gets injected by the
      // renderer.
      this.updater = updater || ReactNoopUpdateQueue;
    }
    
    Component.prototype.forceUpdate = function(callback) {
      this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
    };
    

    The Component function has 3 arguments which is being utilized inside the function. Later, its prototype forceUpdate is defined on which the updater is being hooked to enqueue the forceUpdate with enqueueForceUpdate. So, this.forceUpdate actually calling the Component updater and allows us to re-render the component. I hope, looking at its prototype method makes sense now.


    What is the difference between a prototype function and constructor literal?

    As far as I understand, you wanted to know why constructor is being called with the desired params.

    The class/function constructor is used so that you can use an override to the function. For eg, passing props inside the constructor, you wanted to do an override with this. So, you explicitly notify the function to use the props as used inside the constructor.