Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

React vs. Angular: A Popular JavaScript Library and a Powerful JavaScript Framework

DZone's Guide to

React vs. Angular: A Popular JavaScript Library and a Powerful JavaScript Framework

The main differences between AngularJS and ReactJS have to do with componentization, data binding, performance, dependency resolution, directives, and templating.

Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

Most interactive single-page applications are built with the help of JavaScript (JS) frameworks and libraries. The number of JS tools for fast single-page application (SPA) development is constantly growing, making the choice of which technology to rely on more challenging for us as web developers.

Both React and Angular are currently used by many business, news, and travel companies in the USA, the UK, Canada, France, Germany, Australia, and other countries. AngularJS has been included in virtually every list of top 10 JavaScript frameworks since its release in 2009. This Model-View-Controller framework has become extremely popular among web developers. ReactJS is even more widely used by JavaScript programmers, although it’s actually a library, not a framework; the React library only has a View, but lacks Model and Controller components. So, how did React became so popular, and how can we reasonably make JavaScript frameworks comparisons compare a framework (AngularJS) with a library (ReactJS)?

The main differences between AngularJS (the framework) and ReactJS (the library) are in the following aspects: componentization, data binding, performance, dependency resolution, directives, and templating. Let’s look at each of these aspects separately.

Componentization

AngularJS

AngularJS has a very complex and fixed structure because it's based on the three layers — Model, View, and Controller — typical of single-page applications. An object $scope in AngularJS is responsible for the Model part, which is initialized by the Controller and then transformed into HTML to create the View for the user. Angular provides many standard services, factories, controllers, directives, and other components that will take some time for a JavaScript developer to master initially.

With AngularJS, we break the application code into several files. For example, when we create a reusable component with our own directive, controller, and template, we must describe each chunk of code in a separate file. Once we describe our directive, we then add a link to our template in the directive to couple these parts. AngularJS directives represent the template logic for your application. The template is HTML extended with Angular directives, generally written as tags or attributes. We also add controllers to provide our models with necessary $scope or context. Controllers are written in separate files as well. When we modularize our application in such a way, we can reuse our template or component in a different part of the website.

ReactJS

Facebook, the creator of ReactJS, chose an architecture different from that of AngularJS and similar MVC frameworks. In short, there is no “correct" structure for applications built with ReactJS.

ReactJS is a large JavaScript library that helps us update the View for the user. But ReactJS still doesn't let us create applications on its own. The library lacks the model and controller layers. To fill in the gap, Facebook introduced Flux, which has numerous variants nowadays, to control the application workflow.

ReactJS provides a very simple and efficient way to build component trees. It boasts a functional programming style where component definitions are declarative. Composing your app from ReactJS components is like composing a JavaScript program from functions. Just look at the example below, taken from GitHub:

var TodoApp =React.createClass({
getInitialState:function () {
return {
nowShowing:app.ALL_TODOS,
editing:null,
newTodo:''
};
},
handleChange:function (event) {
this.setState({
newTodo:event.target.value
});
}
});
// other code is omitted for brevity

Code written in ReactJS is logically structured and readable thanks to the availability of components. The ReactJS library doesn’t demand that you write code in a certain way. They suggest that you use JSX (a special XML-like syntax) to create classes and templates, but it’s also possible to write plain JavaScript and HTML. This helps JavaScript developers adapt to React applications more easily, as there is no unusual syntax to learn. React offers a freedom that AngularJS doesn’t. But this freedom comes at the cost of additional time spent designing the structure of an application. Before we start a new project, we have to think about what instruments we are going to use. When you have to pick a tool from among 100 options to resolve a single task, this choice becomes cumbersome.

Data Binding

AngularJS

AngularJS connects Document Object Model (DOM) values to Model data through the Controller using two-way data binding. In short, if the user interacts with an <input> field and provides a new value to the app, then not only the View is updated, but the Model is, as well. Two-way data binding is beneficial for AngularJS as it helps us write less boilerplate code to create interactions between components (the View and the Model) in our application. We don't have to invent a method to track changes in the app and change our JavaScript code accordingly.

The drawback of Angular's two-way data binding approach is its negative impact on performance. Angular automatically creates a watcher for each binding. During development, we may come to a point when an app is packed with too many watchers for bound elements.

ReactJS

React uses one-way data binding, meaning we are able to direct the flow of data only in one direction. Because of this, it’s always clear where the data was changed. It’s worth noting that two-way data binding was available in ReactJS before v15 thanks to ReactLink.

ReactJS Flux workflow

In order to implement a unidirectional data flow in React, Facebook created its own application architecture called Flux. Flux controls the flow of data to ReactJS components through one control point – the dispatcher. Flux's dispatcher receives an object (they call it an action) and transfers it to an appropriate store, which then updates itself. Once the update is finished, the View changes accordingly and sends a new action to the dispatcher. It's only possible to transfer an action to the store when it’s fully updated. With this concept, Flux improves the effectiveness of the code base. Based on our own experience we can say that Flux is great when you work with dynamically updated data.

The one-way data flow in ReactJS keeps complexity under control. It's much easier to debug self-contained components of large ReactJS applications than it is with similarly large AngularJS applications.

Performance

AngularJS

There are two things to take into consideration when we talk about Angular's performance. As we mentioned previously, Angular 1.x and higher relies on two-way data binding. This concept is based on “dirty checking," a mechanism that can make our AngularJS application laggy.

When we bind values in HTML with our model, Angular creates a watcher for each binding to track changes in the DOM. Once the View updates (becomes “dirty"), Angular compares the new value with the initial (bound) value and runs the $digest loop. The $digest loop then checks not only values that have actually changed but also all others values that are tracked through watchers. This is why performance will decrease a lot if your application has too many watchers. This drawback is even more painful when several values (Views) are dependent on each other. Once Angular sees that the change of a value was triggered by another change of a different value, then it stops the current $digest cycle and runs it all over again.

The loop doesn't stop working until it checks all watchers and applies all necessary changes to both the View and the Model. In practice, we can bind an <input> field to different Views and Models. When the user enters new data into the field, the change may not be immediately visible. It’s better to avoid that.

Another shortcoming of the AngularJS framework is the way it works with the DOM. Unlike React, AngularJS applies changes in the real DOM in the browser. When the real DOM gets updated, the browser has to change many internal values to represent a new DOM. This also has a negative impact on application performance.

Poor performance is the main reason why Angular 2 supporters introduced the virtual Document Object Model rendered on the server and one-way data binding similarly to React. Still, Angular 2 offers two-way data binding as an option.

ReactJS

The creators of ReactJS introduced the concept of the virtual Document Object Model, which is regarded as one of the greatest advantages of ReactJS in comparison with mature frameworks, including AngularJS. How does the virtual DOM work? When our HTML document is loaded, ReactJS creates a lightweight DOM tree from JavaScript objects and saves it on the server. When the user, for instance, enters new data in the <input> field in the browser, React creates a new virtual DOM and then compares it with the previously saved DOM. The library finds dissimilarities between two object models in such a way and rebuilds the virtual DOM once again, but with new changed HTML. All this work is done on the server, which reduces load on the browser.

Now, instead of sending completely new HTML to the browser, React sends the HTML only for the changed element. This approach is much more efficient than what AngularJS offers.

As for one-way data binding, React doesn't use watchers to track changes in the real DOM. Overall, ReactJS makes it simpler to control application performance. But this doesn't mean we cannot create a fast application in AngularJS.

Resolving Dependencies

AngularJS

AngularJS uses a basic Object-Oriented Programming (OOP) pattern called dependency injection, meaning we write dependencies in a separate file. It’s inconvenient to create a dependency directly in an object. In AngularJS, dependency injection is inherent to any standard functions that we declare for an Angular factory or service. We only pass dependencies as parameters in any order in our functions. This is where vanilla JavaScript is different from Angular, as the order of arguments in standard JS is strict.

angular.module('todomvc')
// Angular injects four dependencies in the TodoCtrl function – $scope, $routeParams, $filter, and store;
.controller('TodoCtrl', functionTodoCtrl($scope, $routeParams, $filter, store) {
'use strict';
var todos =$scope.todos=store.todos;
$scope.newTodo='';
$scope.editedTodo=null;
// missing function code is omitted for brevity
});

Angular automatically finds appropriate objects that are injected as the $routeParams, $filter, store, and $scope parameters. There are two functions that make dependency injection possible in the Angular framework: $inject and $provide.

We should also mention an issue with dependency injection in AngularJS; a small nuisance you may encounter when you run code minification.

A code minification program reduces dependency names to something like $b and $y for concision. But when executing the code, Angular will look for dependencies by their actual names, which are $scope, $filter, and store in the example above! This is when our program silently crashes. On the bright side, it's very easy to resolve this issue.

As you can see in the example below, we have declared the function TodoCtrl and passed only short names of arguments. Further below, we specifically show what to inject in our function in the necessary order. Therefore, the “s" argument stands for “$scope"; the “r" argument stands for “$routeParams", etc. Angular will find dependencies automatically. This time, pay attention to the order of the arguments.

// an example from GitHub
angular.module('todomvc')
.controller('TodoCtrl', TodoCtrl);

functionTodoCtrl(s, r, f, a) {
'use strict';
var todos =s.todos=a.todos;
s.newTodo='';
s.editedTodo=null;
// missing function code is omitted for brevity
};
//inject dependencies using a special function
TodoCtrl[“inject”] = [“$scope”, “$routeParams”, “$filter”, “store”];


There is also another way to pass a function and its dependencies – by using an array. The first array elements would be your dependencies followed by the function with short parameters.

Another example of how to inject dependencies into Angular module:

[“$scope”, “$routeParams”, “$filter”, “store”, functionTodoCtrl(s, r, f, a) { //your code goes here }];

ReactJS

The difference between React and Angular with regards to dependency injection is that React doesn’t offer any concept of a built-in container for dependency injection. But this doesn't mean we have to think of a method to inject dependencies in our ReactJS project. You can use several instruments to inject dependencies automatically in a React application. Such instruments include Browserify, RequireJS, EcmaScript 6 modules which we can use via Babel, ReactJS-di, and so on. The only challenge is to pick a tool to use.

Originally published here. 

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:
react js ,angular js ,javascript ,web dev

Published at DZone with permission of Sviatoslav Andrushko. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}