Mixing HTML and JavaScript
So ReactJS promotes something that some people consider controversial, tightly coupling the DOM structure to the JavaScript code (generally written in the HTML like JSX syntax). If you look at other frameworks such as Ember or AngularJS, they provide templating systems that promote you to separate the template code from the logic code. There are also a number of general javascript templating systems that do the same thing if you are not using a framework and just using a library like jQuery. When I worked exclusively with jQuery, I agreed with this level of separation. Over the past couple of years of working with more javascript frameworks like Backbone and AngularJS, I have come to see this creates more issues than is solves. Ultimately I believe the template code is tightly coupled with the logic code so it makes sense for them to live in the same file.
For example, lets take an auto complete component. An auto complete component will have some HTML to display the list of auto complete items. It will also have some logic to be able to interact with those items. You can do things like using the keyboard to cycle through them or clicking on one of them to select it. The HTML and logic code are tightly tied together because there is a pretty good chance that if you change one, you are going to need to change the other and they are not useful alone.
What about multiple templates?
One may argue that if you have your template as a separate file, you can create multiple templates that can use the same logic code. For example, with AngularJS, you can define a templateUrl
property of a directive to be a function that can return a number of different strings that will resolve to the url path of the template that you want to use. While this is true, I would argue two things.
First, this is something that I have not commonly had to do in practice. I think being able to use multiple templates against the same logic code is one of those things that in theory sounds great, but it is not exactly a common use case in practice. Most of my 9+ years in web development has been mainly in managing CRUD style web applications and 98% of the time, my logic code was always running against 1 template anyways.
Secondly, when you do have the occasion where you do need this type of functionality, ReactJS provide a more flexible solution in my opinion, mixins. Lets says we want to have a large card and a small card component that will need the same logic. With AngularJS you create a card directive and dynamically generate the templateUrl
for the type of card you need.
angular.module('app')
.directive('card', [
'$compile',
function($compile){
return {
templateUrl: function() {
return something === true ? '/templates/card-small.html' : '/templates/card-large.html';
},
//other properties
compile: function(element, attributes) {
//your logic
}
};
}
]);
Using this directive might look this this:
<card data-type="small" ...></card>
<card data-type="large" ...></card>
With ReactJS I would first create a card mixin.
var cardMixin = {
//your logic
};
Then would create a SmallCard
and a LargeCard
component.
var SmallCard = React.createClass({
mixins: [cardMixin],
render: function() {
//return your template code
}
});
var LargeCard = React.createClass({
mixins: [cardMixin],
render: function() {
//return your template code
}
});
I find mixins to be a much better system of adding functionality to components compared to AngularJS directives. Sometimes something that I would have written as a directive in AngularJS can be just a mixin (but I will leave that for another post).
ReactJS is not ExtJS
One things that I have seen is some comparisons of ReactJS to ExtJS because of the tightly couple template and logic code. While at a high level they both do manage HTML based on JavaScript code, their implementations are so different I don't think they are really that close to each other. I have used ExtJS in the past and it was a very painful experience, the complete opposite compared to ReactJS. Anyone can take a great idea, write a bad implementation, and then use that implementation as a reason why the general idea is bad. ExtJS for me created a bad implementation of using JavaScript to manage HTML but ReactJS created a much more elegant solution.
It should also be mentioned that ExtJS is designed to provide you everything for building a web application from a core framework to a set of components complete with styling and ReactJS is just a library for build components. Comparing all of ExtJS to ReactJS would not be fair however I think just looking at the API for managing HTML is fair.
Lets take a look at a simple panel component, this is from the ExtJS 5.0.1 documentation which I believe is the latest version as of writing this:
var filterPanel = Ext.create('Ext.panel.Panel', {
bodyPadding: 5, // Don't want content to crunch against the borders
width: 300,
title: 'Filters',
items: [{
xtype: 'datefield',
fieldLabel: 'Start date'
}, {
xtype: 'datefield',
fieldLabel: 'End date'
}],
renderTo: Ext.getBody()
});
Now lets assume we have a Panel
, PanelContent
, and DateField
ReactJS components already written, the ReactJS code for the same panel in my head would look like this:
var filterPanel = React.createClass({
render: function() {
return (
<Panel>
<header>Filters</header>
<PanelContent>
<DateField
Label="Start date" />
<DateField
Label="End date" />
</PanelContent>
</Panel>
);
}
});
Now I am not saying the ReactJS's JSX is a perfect system for written HTML in JavaScript, it definitely has it's rough edges, but for me, the ReactJS code is much easier to read and understand. I think it is because it resembles HTML pretty well which is something any front-end developer should already be familiar with. ExtJS basically creates it own custom API that is something you going to have to learn. This is only a simple example, things can become very hairy very quite with what I remember from my ExtJS days.
I should also note that ExtJS does as have css integrated into thier API for creating components but I did not do in the ReactJS version. This post is just about HTML and JavaScript, I will leave the styling aspect for another post.
Sometimes when certain patterns are not recommended (like keeping your template and logic code separate) it is not necessarily because the general idea is bad, it just might be that there is not a good implementation of that idea. I think ReactJS is a very good implementation of the idea that it makes sense to keep your template and logic code together in the same file.