React for Angular Developers

Share this article

React for Angular Developers

This article is for developers who are familiar with Angular 1.x and would like to learn more about React. We’ll look at the different approaches they take to building rich web applications, the overlapping functionality and the gaps that React doesn’t attempt to fill.

After reading, you’ll have an understanding of the problems that React sets out to solve and how you can use the knowledge you have already to get started using React in your own projects.

Frameworks vs Libraries

Angular is a framework, whereas React is a library focused only on the view layer. There are costs and benefits associated with both using frameworks and a collection of loosely coupled libraries.

Frameworks try to offer a complete solution, and they may help organize code through patterns and conventions if you’re part of a large team. However, having a large API adds cognitive load when you’re writing, and you’ll spend a lot more time reading documentation and remembering patterns — especially in the early days when you’re still learning.

Using a collection of loosely coupled libraries with small APIs is easier to learn and master, but it means that when you run into problems you’ll need to solve them with more code or pull in external libraries as required. This usually results in you having to write your own framework to reduce boilerplate.

Recommended Courses

Todd Motto
The ultimate resource to learn Angular and its ecosystem. Use coupon code 'SITEPOINT' at checkout to get 25% off.

Out Of The Box

Angular gives you a rich feature set for building web applications. Among its features are:

  • HTML templates with dynamic expressions in double curlies {{ }}
  • built-in directives like ng-model, ng-repeat and ng-class for extending the capability of HTML
  • controllers for grouping logic and passing data to the view
  • two-way binding as a simple way to keep your view and controller in sync
  • a large collection of modules like $http for communicating with the server and ngRoute for routing
  • custom directives for creating your own HTML syntax
  • dependency injection for limiting exposure of objects to specific parts of the application
  • services for shared business logic
  • filters for view formatting helpers.

React, on the other hand, gives you:

  • JSX syntax for templates with JavaScript expressions in single curlies { }
  • components, which are most like Angular’s element directives.

React is unopinionated when it comes to the rest of your application structure and it encourages the use of standard JavaScript APIs over framework abstractions. Rather than providing a wrapper like $http for server communication, you can use fetch() instead. You’re free to use constructs like services and filters, but React won’t provide an abstraction for them. You can put them in JavaScript modules and require them as needed in your components.

So, while Angular gives you a lot more abstractions for common tasks, React deliberately avoids this to keep you writing standard JavaScript more often and to use external dependencies for everything else.

Bootstrapping

Initializing Angular apps requires a module, a list of dependencies and a root element.

let app = angular.module('app', [])
let root = document.querySelector('#root');
angular.element(root).ready(function() {
  angular.bootstrap(root, ['app']);
});

The entry point for React is rendering a component into a root node. It’s possible to have multiple root components, too:

let root = document.querySelector('#root');
ReactDOM.render(<App />, root)

Templates

The anatomy of an Angular view is complex and has many responsibilities. Your HTML templates contain a mix of directives and expressions, which tie the view and the associated controllers together. Data flows throughout multiple contexts via $scope.

In React, it’s components all the way down, data flows in one direction from the top of the component tree down to the leaf nodes. JSX is the most common syntax for writing components, transforming a familiar XML structure into JavaScript. Whilst this does resemble a template syntax, it compiles into nested function calls.

const App = React.createClass({
  render: function() {
    return (
      <Component>
        <div>{ 2 + 1 }</div>
        <Component prop="value" />
        <Component time={ new Date().getTime() }>
          <Component />
        </Component>
      </Component>
    )
  }
})

The compiled code below should help clarify how the JSX expressions above map to createElement(component, props, children) function calls:

var App = React.createClass({
  render: function render() {
    return React.createElement(
      Component,
      null,
      React.createElement("div", null, 2 + 1),
      React.createElement(Component, { prop: "value" }),
      React.createElement(
        Component,
        { time: new Date().getTime() },
        React.createElement(Component, null)
      )
    );
  }
});

Template Directives

Let’s look at how some of Angular’s most used template directives would be written in React components. Now, React doesn’t have templates, so these examples are JSX code that would sit inside a component’s render function. For example:

class MyComponent extends React.Component {
  render() {
    return (
      // JSX lives here
    )
  }
}

ng-repeat

<ul>
  <li ng-repeat="word in words">{ word }</li>
</ul>

We can use standard JavaScript looping mechanisms such as map to get an array of elements in JSX.

<ul>
  { words.map((word)=> <li>{ word }</li> )}
</ul>

ng-class

<form ng-class="{ active: active, error: error }">
</form>

In React, we’re left to our own devices to create our space-separated list of classes for the className property. It’s common to use an existing function such as Jed Watson’s classNames for this purpose.

<form className={ classNames({active: active, error: error}) }>
</form>

The way to think about these attributes in JSX is as if you’re setting properties on those nodes directly. That’s why it’s className rather than the class attribute name.

formNode.className = "active error";

ng-if

<div>
  <p ng-if="enabled">Yep</p>
</div>

if … else statements don’t work inside JSX, because JSX is just syntactic sugar for function calls and object construction. It’s typical to use ternary operators for this or to move conditional logic to the top of the render method, outside of the JSX.

// ternary
<div>
  { enabled ? <p>Enabled</p> : null }
</div>

// if/else outside of JSX
let node = null;
if (enabled) {
  node = <p>Enabled</p>;
}
<div>{ node }</div>

ng-show / ng-hide

<p ng-show="alive">Living</p>
<p ng-hide="alive">Ghost</p>

In React, you can set style properties directly or add a utility class, such as .hidden { display: none }, to your CSS for the purpose of hiding your elements (which is how Angular handles it).

<p style={ display: alive ? 'block' : 'none' }>Living</p>
<p style={ display: alive ? 'none' : 'block' }>Ghost</p>

<p className={ classNames({ hidden: !alive }) }>Living</p>
<p className={ classNames({ hidden: alive }) }>Ghost</p>

You’ve got the hang of it now. Instead of a special template syntax and attributes, you’ll need to use JavaScript to achieve what you want instead.

An Example Component

React’s Components are most like Angular’s Directives. They’re used primarily to abstract complex DOM structures and behavior into reusable pieces. Below is an example of a slideshow component that accepts an array of slides, renders a list of images with navigational elements and keeps track of its own activeIndex state to highlight the active slide.

<div ng-controller="SlideShowController">
  <slide-show slides="slides"></slide-show>
</div>
app.controller("SlideShowController", function($scope) {
  $scope.slides = [{
    imageUrl: "allan-beaver.jpg",
    caption: "Allan Allan Al Al Allan"
  }, {
    imageUrl: "steve-beaver.jpg",
    caption: "Steve Steve Steve"
  }];
});

app.directive("slideShow", function() {
  return {
    restrict: 'E',
    scope: {
      slides: '='
    },
    template: `
      <div class="slideshow">
        <ul class="slideshow-slides">
        <li ng-repeat="slide in slides" ng-class="{ active: $index == activeIndex }">
          <figure>
            <img ng-src="{{ slide.imageUrl }}" />
            <figcaption ng-show="slide.caption">{{ slide.caption }}</figcaption>
          </figure>
        </li>
        </ul>
        <ul class="slideshow-dots">
          <li ng-repeat="slide in slides" ng-class="{ active: $index == activeIndex }">
            <a ng-click="jumpToSlide($index)">{{ $index + 1 }}</a>
          </li>
        </ul>
      </div>
    `,
    link: function($scope, element, attrs) {
      $scope.activeIndex = 0;

      $scope.jumpToSlide = function(index) {
        $scope.activeIndex = index;
      };
    }
  };
});

The Slideshow Component in Angular

See the Pen Angular Slideshow by SitePoint (@SitePoint) on CodePen.

This component in React would be rendered inside another component and passed the slides data via props.

let _slides = [{
  imageUrl: "allan-beaver.jpg",
  caption: "Allan Allan Al Al Allan"
}, {
  imageUrl: "steve-beaver.jpg",
  caption: "Steve Steve Steve"
}];

class App extends React.Component {
  render() {
    return <SlideShow slides={ _slides } />
  }
}

React components have a local scope in this.state, which you can modify by calling this.setState({ key: value }). Any changes to state causes the component to re-render itself.

class SlideShow extends React.Component {
  constructor() {
    super()
    this.state = { activeIndex: 0 };
  }
  jumpToSlide(index) {
    this.setState({ activeIndex: index });
  }
  render() {
    return (
      <div className="slideshow">
        <ul className="slideshow-slides">
          {
            this.props.slides.map((slide, index) => (
              <li className={ classNames({ active: index == this.state.activeIndex }) }>
                <figure>
                  <img src={ slide.imageUrl } />
                  { slide.caption ? <figcaption>{ slide.caption }</figcaption> : null }
                </figure>
              </li>
            ))
          }
        </ul>
        <ul className="slideshow-dots">
          {
            this.props.slides.map((slide, index) => (
              <li className={ (index == this.state.activeIndex) ? 'active': '' }>
                <a onClick={ (event)=> this.jumpToSlide(index) }>{ index + 1 }</a>
              </li>
            ))
          }
        </ul>
      </div>
    );
  }
}

Events in React look like old-school inline event handlers such as onClick. Don’t feel bad, though: under the hood it does the right thing and creates highly performant delegated event listeners.

The Slideshow Component in React

See the Pen React SlideShow by SitePoint (@SitePoint) on CodePen.

Two-Way Binding

Angular’s trusty ng-model and $scope form a link where the data flows back and forth between a form element and properties on a JavaScript object in a controller.

app.controller("TwoWayController", function($scope) {
  $scope.person = {
    name: 'Bruce'
  };
});
<div ng-controller="TwoWayController">
  <input ng-model="person.name" />
  <p>Hello {{ person.name }}!</p>
</div>

React eschews this pattern in favor of a one-way data flow instead. The same types of views can be built with both patterns though.

class OneWayComponent extends React.Component {
  constructor() {
    super()
    this.state = { name: 'Bruce' }
  }
  change(event) {
    this.setState({ name: event.target.value });
  }
  render() {
    return (
      <div>
        <input value={ this.state.name } onChange={ (event)=> this.change(event) } />
        <p>Hello { this.state.name }!</p>
      </div>
    );
  }
}

The <input> here is called a “controlled input”. This means its value is only ever changed when the `render` function is called (on every key stroke in the example above). The component itself is called “stateful” because it manages its own data. This isn’t recommended for the majority of components. The ideal is to keep components “stateless” and have data passed to them via props instead.

See the Pen One-Way Data Flow in React by SitePoint (@SitePoint) on CodePen.

Typically, a stateful Container Component or Controller View sits at the top of the tree with many stateless child components underneath. For more information on this, read What Components Should Have State? from the docs.

Call Your Parents

Whilst data flows down in one direction, it’s possible to call methods on the parent through callbacks. This is usually done in response to some user input. This flexibility gives you a lot of control when refactoring components to their simplest presentational forms. If the refactored components have no state at all, they can be written as pure functions.

// A presentational component written as a pure function
const OneWayComponent = (props)=> (
  <div>
    <input value={ props.name } onChange={ (event)=> props.onChange(event.target.value) } />
    <p>Hello { props.name }!</p>
  </div>
);

class ParentComponent extends React.Component {
  constructor() {
    super()
    this.state = { name: 'Bruce' };
  }
  change(value) {
    this.setState({name: value});
  }
  render() {
    return (
      <div>
        <OneWayComponent name={ this.state.name } onChange={ this.change.bind(this) } />
        <p>Hello { this.state.name }!</p>
      </div>
    )
  }
}

This might seem like a round-about pattern at first if you’re familiar with two-way data binding. The benefit of having a lot of small presentational “dumb” components that just accept data as props and render them is that they are simpler by default, and simple components have far fewer bugs. This also prevents the UI from being in an inconsistent state, which often occurs if data is in multiple places and needs to be maintained separately.

Dependency Injection, Services, Filters

JavaScript Modules are a much better way to handle dependencies. You can use them today with a tool like Webpack, SystemJS or Browserify.

// An Angular directive with dependencies
app.directive('myComponent', ['Notifier', '$filter', function(Notifier, $filter) {
  const formatName = $filter('formatName');

  // use Notifier / formatName

}]

// ES6 Modules used by a React component
import Notifier from "services/notifier";
import { formatName } from "filters";

class MyComponent extends React.Component {

  // use Notifier / formatName

}

Sounds Great. Can I Use Both!?

Yes! It’s possible to render React components inside an existing Angular application. Ben Nadel has put together a good post with screencast on how to render React components inside an Angular directive. There’s also ngReact, which provides a react-component directive for acting as the glue between React and Angular.

If you’ve run into rendering performance problems in certain parts of your Angular application, it’s possible you’ll get a performance boost by delegating some of that rendering to React. That being said, it’s not ideal to include two large JavaScript libraries that solve a lot of the same problems. Even though React is just the view layer, it’s roughly the same size as Angular, so that weight may be prohibitive based on your use case.

While React and Angular solve some of the same problems, they go about it in very different ways. React favors a functional, declarative approach, where components are pure functions free of side effects. This functional style of programming leads to fewer bugs and is simpler to reason about.

How About Angular 2?

Components in Angular 2 resemble React components in a lot of ways. The example components in the docs have a class and template in close proximity. Events look similar. It explains how to build views using a Component Hierarchy, just as you would if you were building it in React, and it embraces ES6 modules for dependency injection.

// Angular 2
@Component({
  selector: 'hello-component',
  template: `
    <h4>Give me some keys!</h4>
    <input (keyup)="onKeyUp($event)" />
    <div>{{ values }}</div>
  `
})
class HelloComponent {
  values='';
  onKeyUp(event) {
    this.values += event.target.value + ' | ';
  }
}

// React
class HelloComponent extends React.Component {
  constructor(props) {
    super()
    this.state = { values: '' };
  }
  onKeyUp(event) {
    const values = `${this.state.values + event.target.value} | `;
    this.setState({ values: values });
  }
  render() {
    return (
      <div>
        <h4>Give me some keys!</h4>
        <div><input onKeyUp={ this.onKeyUp.bind(this) } /></div>
        <div>{ this.state.values }</div>
      </div>
    );
  }
}

A lot of the work on Angular 2 has been making it perform DOM updates a lot more efficiently. The previous template syntax and complexities around scopes led to a lot of performance problems in large apps.

A Complete Application

In this article I’ve focused on templates, directives and forms, but if you’re building a complete application, you’re going to require other things to help you manage your data model, server communication and routing at a minimum. When I first learned Angular and React, I created an example Gmail application to understand how they worked and to see what the developer experience was like before I started using them in real applications.

You might find it interesting to look through these example apps to compare the differences in React and Angular. The React example is written in CoffeeScript with CJSX, although the React community has since gathered around ES6 with Babel and Webpack, so that’s the tooling I would suggest adopting if you’re starting today.

There’s also the TodoMVC applications you could look at to compare:

Learning Resources

Learning React has been enjoyable, it’s taught me more about functional programming and has a vibrant community around it contributing their own interesting pieces to the React ecosystem. Andrew Ray has written a few great introductory posts on React and Flux, the official React tutorial is the go-to place to get started. Enjoy!

This article was peer reviewed by Craig Bilner. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Frequently Asked Questions (FAQs) for React for Angular Developers

What are the key differences between React and Angular?

React and Angular are both popular JavaScript frameworks used for building web applications. However, they have some key differences. React, developed by Facebook, is a library for building user interfaces, particularly for single-page applications. It’s known for its virtual DOM feature which optimizes rendering and improves app performance. On the other hand, Angular, developed by Google, is a full-fledged MVC framework. It provides a lot of out-of-the-box features like two-way data binding, dependency injection, and directives, which can make it more complex and harder to learn than React.

How do I transition from Angular to React?

Transitioning from Angular to React can be a smooth process if you understand the fundamental differences between the two. Start by learning the basics of React, such as components, props, and state. Then, get familiar with JSX, which is a syntax extension for JavaScript that allows you to write HTML in your React code. Once you’re comfortable with these concepts, you can start building simple applications in React. Over time, you can gradually move on to more complex topics like lifecycle methods, hooks, and context API.

Can I use Angular and React together in a project?

Yes, it’s possible to use Angular and React together in a project. However, it’s not a common practice and it can add unnecessary complexity to your application. Both frameworks have their own strengths and weaknesses, and they are designed to solve different problems. If you find yourself needing to use both, it might be a sign that you need to reevaluate your project’s requirements and choose the right tool for the job.

What is the equivalent of Angular’s ngClass in React?

In React, you can dynamically change classes using the className attribute and JavaScript expressions. For example, you can create an object where the keys are your class names and the values are boolean expressions. Then, you can use this object in your className attribute. This is similar to Angular’s ngClass directive.

How does data binding work in React compared to Angular?

In Angular, you have two-way data binding, which means that changes in the model automatically update the view and vice versa. In React, data binding is one-way. This means that changes in the model update the view, but not the other way around. To update the model, you need to use events and state or props.

How do I handle events in React?

In React, you can handle events in a similar way to how you would in regular JavaScript. However, there are some differences. For example, in React events are named using camelCase, not lowercase. Also, in JSX you pass a function as the event handler, rather than a string.

What is the equivalent of Angular’s directives in React?

React doesn’t have a direct equivalent of Angular’s directives. Instead, you can achieve similar functionality using components and props in React. Components in React are reusable pieces of code that return a React element to be rendered to the page.

How do I use forms in React?

In React, you can create controlled components to handle forms. A controlled component is an input element whose value is controlled by React. This makes it easier to modify or validate user input.

How does React handle state management?

React has a built-in state management system through its state object. However, for more complex applications, you might need to use external libraries like Redux or MobX. These libraries provide more advanced state management features like centralized state and time-travel debugging.

What are React Hooks?

React Hooks are a new addition in React 16.8 that allow you to use state and other React features without writing a class. Hooks are functions that let you “hook into” React state and lifecycle features from function components. They can make your code more readable and easier to test.

Mark BrownMark Brown
View Author

Hello. I'm a front end web developer from Melbourne, Australia. I enjoy working on the web, appreciate good design and working along side talented people I can learn from. I have a particular interest in visual programming so have fun working with SVG and Canvas.

angular componentsangular directivesdependency injectionjameshLearn Angularone-way data flowpropsreact componentsreact-hubReact-Learnscopestatetemplatestwo-way data Bindingunidirectional data flow
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week