Comparing Angular to React
Introduction
Here at cap hpi, we have a number of web applications written with AngularJS. With the launch of Angular, we decided to evaluate whether we should migrate our AngularJS web applications to Angular, or to switch to another framework such as React.
One thing that quickly became apparent was that Angular is a “batteries included framework”. Most notably, it provides mechanisms for making HTTP calls and client-side routing. React, on the other hand, is purely concerned with the “view” element of the application, leaving the developer to choose how they handle other concerns, such as making HTTP calls and routing. In React, views are typically written using JSX, but they don’t have to be.
How can we compare these frameworks?
The approach will be to show several code examples, written with Angular and React, along with links to live examples (using Plunker) so you can review and tweak the code for yourselves.
Wherever possible, We’ll be using ES2015+ syntax for the React examples, as the syntax will be more similar to the TypeScript used in the Angular examples.
Where React doesn’t provide the functionality, an alternative approach to providing the functionality will be provided.
Unless it’s relevant to the comparision, the Angular modules will be omitted.
Hello World
A comparision would not be complete without the obligatory, super-simple Hello World example.
Angular
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `<h1>Hello, world!</h1>` }) export class AppComponent {}
React
ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById(‘app’) );
Data binding
Let’s see a basic example of using data
Angular
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: `<h1>Hello {{name}}</h1>` }) export class AppComponent { name = 'World 2'; }
React
const App = ({ name }) => ( <h1>Hello, {name}</h1> ) ReactDOM.render( <App name="World 2" />, document.getElementById('root') );
You can see Angular uses {{someValue}}, whereas, React uses {someValue}.
Conditionally showing / hiding elements
Angular
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` <div> <h1>Conditional Logic</h1> <div *ngIf="showMessage"> Some awesome message </div> </div> ` }) export class AppComponent { showMessage = true; }
React
const App = ({ showMessage }) => ( <div> <h1>Conditional Logic</h1> { showMessage && <div> Some awesome message </div> } </div> ) ReactDOM.render( <App showMessage={true} />, document.getElementById('root') );
Angular uses the NgIf directive to show / hide elements. In React, as soon as you add a {
you’re in JavaScript and therefore, use short-circuit boolean logic to only display elements based on
a truthy / falsy value
Dealing with lists
Angular
import { Component } from '@angular/core'; @Component({ selector: 'my-app', template: ` <div> <h1>List</h1> <div *ngFor="let item of items"> {{item}} </div> </div> ` }) export class AppComponent { items: string[] = [ 'Foo', 'Bar', 'Baz' ] }
React
const App = ({ items }) => ( <div> <h1>List</h1> { items.map(item => <div key={item}>{item}</div>) } </div> ) ReactDOM.render( <App items={['Foo', 'Bar', 'Baz']} />, document.getElementById('root') );
Angular uses the NgFor directive to show a list of items. In React, you use the map method from the Array prototype in JavaScript. Note, you also need to provide a key attribute to help React detect changes to the list and apply DOM changes.
Getting data
Angular
Since we’re using HTTP, we need to bring the HttpModule into our application’s module:
import { HttpModule } from '@angular/http';
And add it to the imports:
imports: [ BrowserModule, HttpModule ],
Then our main component can use make HTTP calls:
import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; import 'rxjs/Rx'; @Component({ selector: 'my-app', template: ` <div> <h1>Getting data</h1> <div *ngFor="let user of users | async"> {{user.name}} </div> </div> ` }) export class AppComponent implements OnInit { users: any; constructor(private http: Http) {} ngOnInit() { this.users = this.http .get('https://jsonplaceholder.typicode.com/users') .map(res => res.json()); } }
React
class App extends React.Component { constructor(props) { super(props); this.state = { users: [] }; } componentDidMount() { fetch('https://jsonplaceholder.typicode.com/users') .then(response => response.json()) .then(json => { this.setState({ users: json }); }); } render() { return ( <div> <h1>Getting data</h1> { this.state.users.map(user => { return ( <div key={user.id}> {user.name} </div> ) }) } </div> ) } } ReactDOM.render( <App />, document.getElementById('root') );
Angular provides a Http class. In React, how you make HTTP calls is entirely up to you. The example above uses Fetch API to retrieve data. Both examples show how to hook into lifecycle hooks, ngOnInit for Angular and componentDidMount for React.
Routing
Angular
Since we’re using Routing, we need to bring the RouterModule into our application’s module:
import { RouterModule } from '@angular/router';
We also need to bring the components to load for our routes into our application’s module:
import { HomeComponent } from './home.component';
import { AboutUsComponent } from './about-us.component';
And configure the routes:
RouterModule.forRoot([
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: 'home', component: HomeComponent },
{ path: 'about-us', component: AboutUsComponent }
])
Our main application component will host the routes in the router-outlet element:
import { Component, OnInit } from '@angular/core'; @Component({ selector: 'my-app', template: ` <div> <h1>Routing Example</h1> <nav> <a routerLink="/home">Home</a> <a routerLink="/about-us" routerLinkActive="active">About Us</a> </nav> <router-outlet></router-outlet> </div> ` }) export class AppComponent {}
React
const {BrowserRouter: Router, Route, Link} = ReactRouterDOM;
const Home = () => (
<div>
<h2>Home Page</h2>
</div>
)
const AboutUs = () => (
<div>
<h2>About Us Page</h2>
</div>
)
const App = () => (
<Router>
<div>
<h1>Routing Example</h1>
<nav>
<Link to="/">Home</Link>
<Link to="/about-us">About Us</Link>
</nav>
<Route exact path="/" component={Home}/>
<Route path="/about-us" component={AboutUs}/>
</div>
</Router>
)
ReactDOM.render(
<App/>,
document.getElementById('root')
)
Angular provides routing out of the box. In React, again, the choice is yours. The example above uses react-router
Which is best?
It depends. The right framework for you / your team will be based on a number of factors.
C# developers will probably find TypeScript easier to learn, since the syntax is quite similar.
Upgrading existing applications written with AngularJS should be relatively easy, since many of the concepts remain (albeit with slightly different syntax).
React fits very well within existing server-side web applications.
Developers who are strong in JavaScript may prefer having the full power of JavaScript and the flexibility of being able to choose how they handle things such as HTTP requests and routing.
The typical setup for React tends to use ES2015 and beyond, fitting nicely into any open-source development stack.
Which one did we choose?
Since we have a number of existing set AngularJS applications and developers with C# knowledge, we decided that Angular would be the better choice for us.