Creating React components using only ES5 features

Heiker - Jul 25 '18 - - Dev Community

This post will be just a friendly reminder that React "It's just javascript". It's okay to use it without a build step. It's okay to use it to create a tiny interactive component. And you don't have to use ES6+ if you don't want to.

Quick recap on the createElement function

React exposes a function called createElement which is the bread and butter of every component. JSX is actually syntactic sugar that translates to React.createElement calls. It looks something like this:

React.createElement(
    'tagName',       // HTML tag name or a custom component 
    props,           // HTML attributes, custom properties, events, etc...
    children         // a string or a list of components or almost anything
);
Enter fullscreen mode Exit fullscreen mode

Stateless components

This types of component only take props and returns a React element. They don't manage their own state and don't have lifecycle methods. They're perfect to present data that comes from other sources. Without any build step it could look like this:

function Welcome(props) {
    return React.createElement('div', null, 'Hello, ' + props.name);
}

ReactDOM.render(Welcome({ name: 'world' }), container);
Enter fullscreen mode Exit fullscreen mode

Class components

These components can manage their own internal state and have lifecycle methods. Here is the thing, in ES5 we can't use the class keyword to create a component, instead will have to mimic that behavior.

The first thing we will need to take care of is the inheritance. Normally you would use class MyComponent extends React.Component to do that. We're going to take another road, we will "force" the inheritance by overriding the prototype object of our component with the one from React.Component, like so:

function MyComponent(props) {
    React.Component.constructor.call(this);

    // ... code
}

MyComponent.prototype = Object.create(React.Component.prototype);
Enter fullscreen mode Exit fullscreen mode

What's different here from our stateless component is that we call React.Component constructor with the context of our custom component, and that we make sure that the prototype is the one from React.Component. With this in place now our component can use the lifecycle methods and the setState method.

Example code

Now with our new found knowledge we can create some components without setting up a build step, or worrying too much about browser support. Lets do a simple timer:

var container   = document.getElementById('app');

// h is short for hyperscript and it makes everything a little bit easier
var h           = React.createElement;

// This is how we inherit methods like setState from React.Component
Timer.prototype = Object.create(React.Component.prototype);

function Timer(props) {
  React.Component.constructor.call(this);
  var self = this;

  self.state = { seconds: 0 };

  self.tick = function() {
    self.setState(function(prevState) {
      return { seconds: prevState.seconds + 1 };
    });
  };

  self.componentDidMount = function() {
    self.interval = setInterval(self.tick, 1000);
  };

  self.componentWillUnmount = function() {
     clearInterval(self.interval);
  };

  self.render = function() {
    return h('div', null, 'seconds: ', self.state.seconds);
  }
}

ReactDOM.render(h(Timer), container);
Enter fullscreen mode Exit fullscreen mode

Notice here that I'm assigning the this context in a self variable to avoid using the bind method of the Function prototype. And I'm using it everywhere just for consistency sake, though I believe is only necessary in self.tick where I would lose the this context when using it in setInterval.

One last thing

One thing people don't notice at first is that the children of an element are also parameters. You can pass a component, a string, an object or a function. At the end of the day children is a prop.

Let me show you something.

Conclusion

This works, and is not that bad. This just shows you that you can use React with the good old script tags to embed it in any site. Another thing that shows is that React Component are function calls, you can do anything that you can think of. Really, you can do anything, including shooting your self in the foot so be careful.

Other resources

Todo List example
Timer example
React without a build step
React is just JavaScript


Thank you for reading. If you find this article useful and want to support my efforts, buy me a coffee ☕.

buy me a coffee

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player