In our comparison, we’ll mention the advantages of ReactJS and the benefits of Angular, showing how these two tools might meet slightly different needs.
Angular 2 vs React: A Short Review of Features
As a brief introduction, let’s take a look at some of the key features of these frameworks:
- Angular 2 is a fully-fledged web framework, whereas React is a library. That said, for the purposes of this review we’ll treat React as a JS framework because React is always used alongside some JS library that provides an architecture for React-based apps. Such libraries include Flux, MobX, and Redux.
- Angular 2 and React are both modular; i.e. you’ll need to use modules in order to develop various functionalities such as routing or managing dependencies in single-page applications.
- React updates the DOM rapidly thanks to its virtual DOM. And in a successful attempt to beat React’s virtual DOM technique, Google has implemented the change detection mechanism in Angular. Therefore, the performance of both Angular and ReactJS is now good enough for any modern web app.
- Both React and Angular work with module bundlers such as Webpack.
For convenience, we'll put other notable features in the table:
Two-way data binding
One-way data binding
Uses built-in framework for managing dependencies
Requires ReactDI to manage dependencies
Flexibility in use
Inflexible (very prescriptive)
Difficult (for advanced JS developers)
Easy (for intermediate JS developers)
There are many more aspects that we will discuss about these frameworks. When choosing between Angular 2 and React for a single-page application, you should be aware of the following:
- How they implement a component-based architecture;
- How they manage application states;
- What JS-based languages they work with;
- What routing capabilities they provide;
- How they implement dependency injection, if any;
- How they make templates dynamic.
React vs Angular 2 in Terms of Component-Based Architecture
Here’s an example of how we can create a component in React:
As you can see, we first have to import React from the core library so our custom component can inherit from (extend) React.Component. (We must import React for every new component we create.) In the render function, the component must return some JSX markup (we’ll talk more about JSX later).
React doesn’t really offer us any specific way to manage styles. We can, for example, create an object with styles and then interpolate values from that object to JSX. Alternately, we’ll need to follow the usual rules: include links to stylesheets in the head tag of the index.html file (you’ll have a single index.html file where your entire application is uploaded – remember, we’re talking about a single-page application).
A typical Angular 2 component looks very different from a React component:
With Angular, you can insert your template and styles directly into a component – though this isn’t advisable unless your template and styles take only few lines of code. In real-world Angular 2 apps, components don’t contain layouts and stylesheets. You’ll want to split each component into three parts: logic, layout, and styles. Therefore, a component will look like this:
The implementation of components is where you’ll find a stark difference between Angular 2 and React. The layout of a React component is always located in the same file as the component’s logic, whereas Angular 2 components let you divide the logic from the layout.
Having templates located alongside component logic in React apps might seem inconvenient at first sight, as the component file will grow larger and more tedious to navigate. On the other hand, when you have the component logic and template in the same file you don’t need to jump constantly between files.
So far, it seems that Angular 2 and React both manage a single component quite effectively. But you’ll create many components for your single-page applications; an app must be divided into small meaningful units each containing specific logic.
With both Angular 2 and React, you’ll want to create one main component that will hold together all other parts of your app, so to speak. That’s quite easy to do with both frameworks by simply using the ES6 import/export feature. React manages multiple components like this:
You’ll have to export Header, Footer, Section components from their respective files. Each sub-component can in turn include other sub-components: for example, a Header can have a Title, and a Section can have several Article components.
Angular does the job quite similarly to React. An Angular AppComponent can import a sub-component (say, a LaptopComponent) and then insert it into the layout as a custom HTML element:
With Angular, you’ll just have to take one more step: all smaller components must be added to the application module file. More specifically, you’ll need to add our hypothetical Laptop component to @NgModule next to the other components:
That’s all we need to mention about the differences between React and Angular in terms of component-based architectures. Let’s summarize what we’ve reviewed so far:
- Angular 2 and React both allow you to build applications from multiple separate components.
- Both frameworks recommend that you to break complex components into simpler units.
- Angular 2 recommends separating complex templates from the component logic; React does the opposite, storing templates and component logic in the same file.
- Angular 2 uses component-related stylesheets and separates them in additional files; React doesn’t suggest any specific way to manage CSS stylesheets.
State Management in React and Angular 2
Managing an application’s state is a challenging task. And it becomes a real disaster when several app components can mutate a shared state:
Does this view update another view? Okay, but that other view also updates yet another view. Hold on, there’s this fourth view that’s getting updated as well. Yep, we can call this a disaster.
What exactly does Redux do? In a simple React-based app, you can keep the application state in layout-level components. But will this solution be future-proof? That’s debatable. If your SPA is going to handle complicated data flow scenarios or complicated chains of events, then you’ll need a better method of management, which is what Redux gives you.
As this diagram shows, Redux uses one-way data flow, which makes handling your program’s state very convenient.
When you start building a React-based application with Redux architecture, you give the app an initial state, which is stored in a single store. With Redux, we don’t mutate the original app state when the application’s state changes (for instance, when the app updates the view to show a new guest). Instead, we create new versions of the same store. In such a way, we can track the full history of our React app way back to the time when we bootstrapped the first version. With Redux, you can save every little change that’s ever happened to an application’s state. That’s great for debugging and makes development predictable.
Redux wraps your entire application into the provider, which is a component of the Redux architecture that listens to the store and re-renders app components after every change. Note that re-rending app components isn’t a problem for React thanks to its virtual DOM.
Finally, Redux introduces reducers. Reducers are functions that accept the current state of a component along with an action. A reducer must create a new state object based on this action object and update the store, after which the Redux circuit (application flow) is closed. And here’s one more thing to know about reducers: Redux-based React applications have multiple reducers, and each reducer modifies only its own piece of data in the store.
Both Angular 2 and React are used to build advanced, enterprise-level single-page applications with intricate logic. The fact is that you might need to learn how to manage an app’s state in Redux whether you’re using React or Angular. As such, we can’t really say that these frameworks differ with regard to state management.
Choosing between JSX and TypeScript for React and Angular 2
Each property of the laptop model above is assigned its own type. The compiler will then compare each laptop object with the above model and alert you if a component is assigned an incorrect value. Here’s pseudocode with an array of laptops in the actual LaptopsComponent:
The Laptop[ ] syntax in our example tells TypeScript to consider the laptops variable as an array of Laptop objects. And if the cost field contains anything other than a number, TypeScript will warn us.
JSX is vastly different from TypeScript with regard to its syntax. You’ve actually seen some JSX in our previous examples of React components:
In the background, the code in the return() function will transpile to the following snippet:
JSX is actually the language of everything you’ll write in the render() function in every React component. Though JSX looks like HTML, it actually has nothing to do with HTML. The code within the render function will always transpile to a JS object with a set of properties.
Facebook strongly recommends using JSX, but you’re not obliged to use it when building React applications. You can simply stick with vanilla JS if you like. For example, to create a template, you can simply call the createElement function with a bunch of arguments – the name of the HTML element, the inner HTML, and so on – instead of writing JSX. Still, this may not the best approach, and in real-world React applications, you’ll almost always stick to JSX.
JSX is easy to read; it’s easy to get used to; and writing JSX is simpler than writing endless JS functions. We can go so far as to say that React and JSX are nearly the same creature. It’s best to embrace this Facebook-created language and use it in your React-based applications.
In short, you’ll have to deal with either TypeScript or JSX when using the Angular 2 framework or the React library. But don’t worry – TypeScript and JSX will feel natural very soon.
Routing with Angular 2 and React
A single-page application that doesn’t route to different pages isn’t really a single-page application. With properly implemented routing, our app can navigate to various pages; use child routes; benefit from lazy loading; and manage access to certain pages, for instance prohibiting users from visiting a page unless they’re authenticated.
Because routing is such a basic necessity for an advanced single-page application, Angular 2 and React must offer us some way to manage routes. But actually, neither of these frameworks comes with routing capabilities in their core libraries. You’ll have to install additional libraries called Angular Router and React Router. These routers work similarly – they just take a specific path as an input and load the component linked to that path.
In code, routing with React will look something like this:
That’s the simplest implementation of routing in a React-based application. Instead of directly rendering the main layout and other components, you use a custom element called Router, which wraps all routes, including the index route. You then need to specify the path and a respective component for each route and implement navigation links on the main page so users can switch between pages.
With Angular 2, routing is quite different than React in some regards. We have to configure routes first and specify the base layout where routes will be loaded. The base layout is usually the index.html file: we’ll need to include the ‘base’ tag into the head tag to let the Angular Router know where it can load routes.
In React you can configure routes in the same file that uploads the entire application, but Angular prefers a more modular approach:
All the code above is stored in a separate file, which we might call something like app.routing.ts. We’ll have to specify at least two properties for each route – a component and a path. Note two more things about routing with Angular: how to check the type of route objects and how to route to sub-components. We can indicate the type for route objects using the Routes module, so the compiler will warn us if we don’t specify a path or component for any route. As for routing to sub-components, we can use variables, for example, :user as shown in the previous code sample to specify a sub-route that can lead to each user profile: https://my-single-page-app.com/users/user.
Angular’s Router goes from the first to last route of the routes array and loads the first component that matches a given route. That’s why, for example, you shouldn’t place the path “**” for a 404 page first in the list of routes, because this path will match any route. The React Router also checks the matching paths from top to bottom in the Router tag, and if the path “*” goes first, other routes will never load. Keep that in mind when building apps with Angular 2 and React.
As a quick recap, both frameworks require additional modules for routing. Angular demands using a separate file for routing and setup before you include a module in an app. React works fine when you specify routes in the main JS file, so there’s no need to create additional files for routing.
Dependency Injection in Angular 2 and React
Dependency injection (DI) is another concept that sets Angular 2 and React apart; DI is an inherent part of the Angular framework, while in React there’s no strictly defined DI mechanism.
In Angular applications, dependency injection allows us to avoid duplicating the same class with the same data in different components. Say, you have two components: One component is a parent, and the other component is a child. They usually share the same data, such as a model (a user or an item model) and the array of objects (users or items). Without dependency injection, you would have to copy and paste the model and array from the parent to its child component. But Angular 2 helps you avoid this by using the @Injectable module and a special service class:
This service must also be registered in the NgModule in the providers array, and that’s it. You can remove the duplicated code from parent and child components and simply use the inject service.
Angular automatically creates a dependency injector that you can feed with all service objects that contain the same information to be used by multiple components. This is a more prescriptive way of managing shareable data than what React offers.
So how can you feed shareable data to multiple React components? React requires a special library, called ReactDI, for managing dependencies. With this library, it’s possible to register all service classes and pass them to any component. Within components, you can call for a necessary service using the di() function and passing that function a service.
Binding Data with Angular 2 and React
React works only with one-way data binding, however, meaning the logic goes from the template to a component and then from the component to the template. HTML templates in React have to use the onChange event and an associated function to respond to user input:
To change the value in the paragraph above, the input field calls for an event handler, changeInputValue, which is written into the component. When you type new text into the input field, the onChange event gets triggered and the changeInputValue function updates the app’s state. The change is eventually reflected in the view part of the app. Therefore, in React the logic goes from a template to a component, and then from a component to a template. This is one-way data binding.
Now let’s take a look at Angular. In the early days, Angular 1.x popularized the magical two-way data binding, albeit AngularJS suffered from slow performance precisely because of this feature. So Google looked at what Facebook achieved with one-way data binding in React and ultimately decided to bring the same feature to Angular.
Angular now uses one-way data binding. Data in Angular flows from a component class into an HTML element property to represent a value. This is called property binding. Data also flows from the HTML template to the component class for calculations in response to certain events like a mouse click or hover. This is called event binding.
The following example demonstrates both types of bindings in Angular 2:
This is how binding works: we click a list item and the template registers a click event. The flow then goes to the component class, where we defined the function selectTeam. This function does something, for example makes the current team active. Then the flow goes backwards – from the component class to the HTML template. Angular will evaluate the string “team === activeTeam” and set the active class for the list item we just clicked. Finally, the background color is changed after the class property has been changed due to property binding. Although the equivalent code in React and Angular looks different, the way the code works is identical.
But knowing that one-way data binding wouldn’t be enough to beat React, Angular has also retained its superpower: banana-in-the-box syntax that makes it possible to create two-way data binding to keep template changes in sync with component changes.
The above is an example of two-way data binding at work in a simple Angular application. To use this cool feature like we’ve shown above, you need to include the FormsModule in your app and bind a necessary value using the NgModel binding in the template. And since Angular supporters have completely re-worked two-way data binding, you won’t find the same performance overhead in Angular now that existed previously.
Angular 2 and React make it really simple to dynamically bind and change HTML element values and component logic in your applications. The only difference between these two frameworks is how their code looks and that one extra feature – two-way data binding – that is available only in Angular.
Adding Dynamic Behavior to Angular 2 and React Apps
In your single-page application, you’ll want to alter the layout by adding, removing, or replacing HTML elements, and Angular 2 and React take different approaches to managing elements. Structural directives is yet another big thing that differentiates Angular from React. There are more than 70 ready directives that you’ll need to use in Angular. Directives allow you to add dynamic behavior to your application.
This is how you can run through an array of objects in an Angular template:
The *ngIf directive lets you verify if the Teams array exists. The *ngFor directive lets you use the for-of loop directly in the HTML template. The actual evaluation of expressions happens behind the scenes, and your sole task is to interpolate values into HTML elements.
React employs a very different approach. For instance, you have to explicitly use array methods to inject values into the layout:
And note that before the component is rendered with the list of teams, we also check if the Teams array contains any team at all (if the length of the array is greater than 0).
If you’re choosing between Angular 2 and React for building a single-page application, there’s no right or wrong option. Angular 2 and React are simply quite different in many aspects. Angular wants you do things a certain way and you can’t avoid its rules – think of directives and the obligatory dependency injection framework. React and its ecosystem provides a looser framework. The best idea is to try out each framework and then decide which works best for you.