The modern world of programming, and especially the web and javascript is not the same for a long time and has a very large number of tools for a particular task. In today's post, I would like to tell you how to cross the power of AngularJS and the lightning speed of the view - Facebook React.
Everyone knows that when we generate a collection in view through Angular, each element of this collection becomes observable. Of course, I understand and I know that there is a certain set of libraries and solutions for how to get around this, but today this is not about that. What does React give us? Well, one of its advantages is the jsx syntax, which is nothing but html in javascript. It is also possible to create reusable components, inherit them and use all the power that this library allows you to do. What we get started.
First of all, create a simple project with the commonplace name ng-with-react. To install the libraries I will use bower. With it, we install AngularJS, ReactJS and Twitter bootstrap so that our application has at least some presentable appearance. Create index.html and main.js which will have the code:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>AngularJS with Facebook react</title> <link rel="stylesheet" href="app/vendor/bootstrap/dist/css/bootstrap.css"/> <style> .user-list .user-item { border-left: none; border-right: none; } .user-list .user-item:last-child { border-bottom: none; } </style> <script src="app/vendor/angular/angular.js"></script> <script src="app/vendor/react/react.js"></script> <script src="app/main.js"></script> </head> <body ng-app="app"> <div class="container" ng-controller="MainCtrl as main"> <div class="page-header"> <h1>A experiment with AngularJS and ReactJS</h1> </div> <div class="panel panel-default"> <div class="panel-heading">Just AngularJS</div> <ul class="list-group"> <li class="list-group-item" ng-repeat="user in users" ng-click="main.getUser(user)"> {{ user.firstName }} - {{ user.lastName }} </li> </ul> </div> </div> </body> </html>
AND
')
(function(ng, React) var app = ng.module('app', []); var UserFactory = function() { var users = [ {id: 1, firstName: "Denis", lastName: "Stoyanov", age:26}, {id: 2, firstName: "Alex", lastName: "Alexeev", age:24}, {id: 3, firstName: "Peter", lastName: "Petrov", age:21}, {id: 4, firstName: "Ivan", lastName: "Ivanov", age:20} ]; return { users: users }; }; var UserCtrl = function($scope, $log, User) { $scope.users = User.users; this.getUser = function(user) { $log.info('A selected user %O', user); }; }; app.factory('User', [UserFactory]); app.controller('MainCtrl', ['$scope', '$log', 'User', UserCtrl]); return app; })(angular, React);
Respectively.
What we have in the arsenal now. We have the simplest application on ng in which there is a simple controller and service that gives fake data. On the presentation side, we have a simple list that renders our data. We also have a handler by clicking on the element that writes the user to the console. It's pretty simple and easy.
Now let's create a new directive to display the same data, but only through ReactJS. As befits the best houses in Paris, we should use directives to manipulate the DOM. First, create a React class to render the list. Its code will look something like this:
var UserList = React.createClass({ displayName: "UserList", render: function() { var users = this.props.scope.users; var scope = this.props.scope; var userList = users.map(function(user, index, array) { var clickHandler = scope.$apply.bind(scope, scope.userSelected.bind(null, {user: user})); return React.DOM.li({ className: "user-item list-group-item", onClick: clickHandler }, [user.firstName, user.lastName].join(' - ')); }); return React.DOM.ul( {className:"user-list list-group"}, userList); } });
As you can see in the React properties there are a number of variables that we will need to pass by simply passing the scope to the React class. We will also create a directive that will use this class as a representation.
var UserDirective = function() { return { restrict: 'AE', scope: { users: '=', userSelected: '&' }, link: function(scope, element, attrs) { scope.$watchCollection('users', function() { React.renderComponent(UserList({scope: scope}), element[0]); }); } }; }; app.directive('userList', UserDirective);
It shows that we will use it as an element or attribute, data with users and a function for displaying the user to the console will be transferred to it. So that our view is displayed when the collection is changed and we create the simplest watcher and redraw our view to change it. Finally, we will render our React class to the element on which the user-list attribute was hung. After rendering on Angular, add the following code to index.html:
<div class="panel panel-default"> <div class="panel-heading">AngularJS with ReactJS</div> <div user-list users="users" user-selected="main.getUser(user)"></div> </div>
With such simple manipulations we tied Angular and React. The application is the simplest, but it makes the concept clear and can be further complicated. According to my tests, at 2000 items view on React was 5 times faster than on Angular.
In the screenshot we can see that the view on React has no binding, unlike AngularJS.

We can also see what React has generated for us.

I hope my experiment will be useful to someone. I believe that it is necessary to build solutions according to their capabilities, and if it is more convenient to write presentations on ReactJS and they are faster in displaying, then I will do so.
If there are any nuances, welcome in comments =)
Sample Code
Source