React versus Angular

In this article I will present my thoughts on the comparison of the popular Web Development frameworks Angular and React. Much has been written about this subject, and it is easy to find websites that provide more details and more arguments for this comparison than I will do here. I will only give my general impression of both frameworks after some years of experience with them.

React and Angular both have the same component model. It is possible to convert an Angular application into a React application, and do this with a one-on-one mapping of the components. The component model of Angular 2 (and higher) is different from the component model of AngularJS, the first version of Angular. I am not discussing AngularJS here, Angular 2 (and higher) has a matured component model, and comparable to that of other frameworks like React. The component model is concerned with structuring of the application at the highest level. This is in my opinion the most important and most pervasive property of a framework. The fact that React and Angular share the same component model means that both frameworks are similar when viewed from a distance. When zooming in on details, there are many differences though.

The main difference between React and Angular is in the template model. The template plays a role within each component, and specifies an outline of the HTML that the component is supposed to produce. The template is a chunk of HTML that has to be completed by inserting concrete data at certain spots and/or by repeating certain parts of it and/or by conditionally showing or suppressing certain parts of it. The way in which a template is processed into a finished piece of HTML that can be rendered by a browser is completely different in React and Angular. In Angular the control structures for processing the template are embedded in the template. In React the template is embedded in the control structures for processing the template. The ways in which templates are processed are therefore completely opposite for both frameworks. Two little examples to show the difference between React and Angular template processing.

const entries = this.props.hofList.sort(this.compFunc).map((entry, index) => (
	<tr key={'hofEntry-' + index}>
		<td style={tableElementStyle} >{entry.name}</td>
		<td style={tableElementStyle} >{Util.formatDate(entry.date)}</td>
		<td style={tableElementStyle} >{entry.moves}</td>
		<td style={tableElementEdgeStyle} >{Util.formatPlayingTime(entry.time)}</td>
	</tr>
));

In this piece of JavaScript React code, a table with four columns and variable number of rows is constructed (it is a piece of code from Connected Sums Game). The template consists of the easily recognizable HTML elements “tr” and “td”. Of course this part of the template has to be inserted into a “table” element to become a valid table that can be displayed by a browser. The template is enriched with data and CSS style information with JavaScript expressions between accolades {,}. Moreover, the template is embedded in a JavsScript anonymous function that is part of a map construction, mapping a list containing data to be shown to a chunk of HTML in which the template part is repeated as many times as there are entities in the data list. The embedding of HTML templates in JavaScript control structures is essential for React and distinguishes it from Angular.

<div class='boardRoot'>
    <div class='board' [ngStyle]='boardStyle'>
        <GameCell *ngFor='let cellValue of state.cells; let id = index'
            [value]='cellValue'
            [id]='id'
            restrictedMoves='boardConfig.restrictedMoves'
            addInc='boardConfig.addInc'
            subDec='boardConfig.subDec'
            hint='this.state.hint'
            gameOver='this.state.gameOver'
            type='boardProps.boardType'
            valueColors='boardConfig.valueColors'
            (buttonClick)='handleSumCommand($event)'
        ></GameCell>
        <ScoreCell title='Moves:' [score]='state.numMoves'></ScoreCell>
        <ScoreCell title='Time:' [score]='state.playingTime'></ScoreCell>
        <br/>
        <GameOverDialog *ngIf='state.gameOver' (buttonClick)='onButtonClick($event)'></GameOverDialog>
    </div>
</div>

In this piece of HTML Angular code, a playing board with a number of game cells is constructed (it is also a piece of code from Connected Sums Game). The template is easily recognizable as HTML on the top-level, with a number of attributes that are Angular specific. The attribute names with an asterisk "*" in front of it represent embedded control structures. The attribute *ngFor in the “GameCell” element signifies that the GameCell element has to be repeated zero, one or more times, depending on the number of elements in state.cells. The attribute *ngIf in the “GameOverDialog” element signifies that GameOverDialog is to be displayed conditionally, depending on state.gameOver. The embedding of control specifiers like *ngFor and *ngIf within HTML templates is essential for Angular and distinguishes it from React, where the relation between template and control is exactly the other way around.

What is the better alternative? Embedding templates within control structures or embedding control structures within templates? In my view the React way of working is more intuitive, easier to learn and more elegant. Why? Frameworks like React and Angular are meant for building highly dynamic websites. They have somehow to produce valid HTML that a browser can display. These frameworks therefore offer means to manipulate HTML. HTML is the subject of the processing that the frameworks support. HTML is the clay, and the framework is the tool with which the potter can make the pottery of his liking. The HTML to be processed is formed by the template concept in both frameworks under discussion. Because HTML is the ultimate subject of processing, it is more intuitive, more logical and more elegant that means to manipulate this subject are not embedded in the subject, but that the subject is free from any distraction that hampers objective view of it. The React way of working is therefore in my view the better solution. Embedding control structures within a template to be controlled is an example of the cart before the horse, and I think it is difficult to find other examples of data processing frameworks where information to manipulate data is embedded within that data. Data that is subjected to processing has to be available for objective inspection, without distractions and pollution.

There is another way of looking at it. In React, the template code is embedded in the JavaScript control structures. Therefore the template and its surrounding control structures is essentially JavaScript. It appears that what looks like HTML template code is essentially a shorthand notation for JavaScript function calls from the React library. This shorthand HTML resembling code is what is called JSX in React. It looks like HTML, and it is designed to look almost identical to HTML but is not HTML because there are certain important restrictions and differences with HTML. In Angular, the situation is exactly the opposite. The control structures are embedded in the HTML template, so the whole is essentially HTML. The means to control template processing are available as HTML attributes, so the whole is and remains HTML. What would a programmer like to work with? With JavaScript or with HTML? The answer is not surprising. In the React philosophy the framework presents itself as a JavaScript library. Templates are embedded in JavaScript, and can be thought of as convenience notation of JavaScript library functions. The programmer therefore feels at home, as he can work in his familiar programming language environment. In the Angular philosophy part of the framework is HTML. In a convoluted way HTML is enriched with certain attributes, to make a little bit a programming language from HTML. The programmer might not quite feel at home, as he has in fact to learn a new programming language. Angular is therefore more a framework, where React is more a library.

I will give some examples of the conceptual simplicity of React over Angular. In Angular the propagation of events up in the DOM tree requires an EventEmitter object that has to be declared before use and that has to be used in the right way, i.e. one has to know its public interface. The same propagation of events is in React done with a simple JavaScript function that is passed down the DOM tree as a property and that has to be called when an event occurs. The Angular EventEmitter object works perfect, but it is an extra concept in the chain of event propagation that seems not necessary, since React demonstrates that we can live without it.

Other example: In Angular we have pipes for among others the formatting of values from the model into the view. Usage of pipes requires knowledge of the PipeTransform interface, import of the PipeTransform interface and Pipe annotation from the angular core library, and knowledge of the special notation for usage of pipes, with the vertical bar. In the end, a pipe is just a function that transforms a value from one representation into another. That is easy to see when viewing the PipeTransform interface. The interface has just one function transform that does all the work. The Angular pipes work perfect, but it is an extra concept in the rendering of views based on models that seems not necessary, since React demonstrates that we can live without it. In React we use just ordinary JavaScript functions to transform a value before it is rendered. Suppose we have two transformations trans1 and trans2 that we want to apply to a value value before we render it on a page. The Angular way with pipes leads to a construction like {{ value | trans1 | trans2 }}. The React way with ordinary functions leads to a construction like { trans2(trans1(value)) }. In my view, the React way wins on conceptual simplicity. We only have to be familiar with JavaScript. No need for an additional concept of pipes, with their interfaces and special notations.

Other example: In React we can use both class variables (from the model class) and local variables in the template. In Angular it is only possible to use the class variables from the model in the template. To do this in Angular, one can refer to the class variables without prefixing it with this., the usual way of referring to class variables in JavaScript. In React, one can just write any JavaScript expression at points in the template that have to be completed with values. To access this mode, just enclose the JavaScript expression with single braces {,}. Between the braces, one can write any JavaScript expression that refers to class variables, methods, functions and local variables that are in scope at that point. What is in scope is evident because the template consists of JSX, which is essentially a shorthand for JavaScript. Finishing a template with concrete values is therefore just JavaScript programming, with all possibilities available. Not so with Angular. To access class variables from the model class in the template, one has to refer to it in a non-standard way: omitting the in JavaScript mandatory prefix this. Local variables are not available at all, because the template is not evaluated in the context of a function but only in the context of the model class. To access class variables for value substitution at child positions (between tags) in the template, one has to refer to these class variables from within double braces {{,}}. To access class variables for value substitution at attribute positions (within opening tags) in the template, one has to refer to these class variables by putting the attribute name between brackets [,] and refer to the variable name without this. prefix in the attribute value between quotes. To access class methods for event handling, one has to refer to these class methods by putting the attribute name between parentheses (,) and refer to the method name without this. prefix in the attribute value between quotes. It is all non-standard and seemingly inconsistent compared to the simple JavaScript way of accessing the model from the template in React. Again, React wins on conceptual simplicity.

Having said this, the template-control relationship is only one point of substantial difference between React and Angular. There are a number of other differences where Angular might have the better features. Angular, especially the newer versions after AngularJS, are mature and well designed frameworks, that are perfectly suited to build complex and large enterprise web applications. The template-control relationship is not that important if one designs components with fine granularity. Breaking up the entire application in many small components will keep the size of the templates in check. A well designed component should have a template with no more than just one or a few control primitives in it. With small components and small templates, the Angular templates will not become unclear.

Because of the more intuitive React approach of template processing, React is easier to learn than Angular. It took me no more than a few hours to learn the basics of the React framework. React also is better suited for rapid prototyping. However, when building large enterprise web applications, Angular might be a better choice.