Using React inside an Angular app

Why?

  • Performance
  • Use existing component
  • Benefit from the easy way to think about data flow that React offers
  • Migrate or do experiments in an existing app

Why not?

  • A new abstraction layer is always costly
  • Have to know both frameworks to work on the project

Examples

GDevApp

Allomatch

How

npm install react react-dom
var React = require('react');
var ReactDOM = require('react-dom');
 
class MyComponent extends React.Component {
  render() {
    return <div>Hello World</div>;
  }
}
// Somewhere in a controller
ReactDOM.render(<MyComponent />, angular.element("#here"));

Data binding

  • Angular 1 two-way binding

DOM

scope

scope changed

DOM event

Update to the DOM done during a digest cycle.

Data binding

  • React one-way data flow

DOM

State

rendering

Component

Component

Component

State

DOM event

this.setState({ text: "Hello world" });

The UI (i.e: the DOM) is a function of the state

Rendering is done after a call to setState

props

props

Pass scope variables to React props

class UserCard extends React.Component {
  render() {
    return <div>Hello { this.props.username }</div>;
  }
}
// Somewhere in a controller
scope.$watch('userdata.username', (username) => {
  ReactDOM.render(
    <UserCard username={username} />, 
    angular.element("#here")
  );
});

Pass scope variables to React props

class UserCard extends React.Component {
  render() {
    return <div>Hello { this.props.username }</div>;
  }
}
// Somewhere in a controller
scope.$watch('userdata.username', (username) => {
  ReactDOM.render(
    React.createElement(UserCard, {username: username}), 
    angular.element("#here")
  );
});

Update scope

class UserCard extends React.Component {
  onClick() {
    // ... whatever ...

    // Let our parent know that we've being clicked :D
    this.props.onClick(); 
  }

  render() {
    return (
      <div> 
        Hello { this.props.username }
        <button onClick={this.onClick} />
      </div>
    );
  }
}

Update scope

// Somewhere in a controller
onUserCardClicked = () => {
  scope.dataRegistered = true;
  $http.post(...);
};

scope.$watch('userdata.username', (username) => {
  ReactDOM.render(
    <UserCard 
      username={username} 
      onClick={onUserCardClicked}
    />, 
    angular.element("#here")
  );
});

// /!\ This won't works :O
// Somewhere in a controller
onUserCardClicked = () => {
  $scope.$apply(() => {
    scope.dataRegistered = true;
    $http.post(...);
  });
};

scope.$watch('userdata.username', (username) => {
  ReactDOM.render(
    <UserCard 
      username={username} 
      onClick={onUserCardClicked}
    />, 
    angular.element("#here")
  );
});

Clean up

class MyComponent extends React.Component {
  // ...
  componentWillUnmount() {
    console.log("Damn, I'm being destroyed");
    this.myPromise.cancel();
    cancelTimeout(this.myTimeout); 
  }
}
// In the Angular controller:
scope.$on('$destroy', function() {
  ReactDOM.unmountComponentAtNode(elem[0]);
});

ngReact

  • Does what we saw for you

module.directive('userCard', function(reactDirective) {
  return reactDirective('UserCard', ['username']);
});
<!-- In a template: -->
<user-card username="username" />

What about Angular 2?

npm install angular2-react --save
tsd install react react-dom --save
import {Component} from 'angular2/core';
import {ReactComponent} from 'angular2-react/component';
import MyComponent from './MyComponent';

@Component({
	template: '<react-component 
             [component]="embedComponent" 
             [props]="embedComponentProps">
        </react-component>',
	directives: [ReactComponent]
})
export class AppComponent {
	embedComponent = MyComponent;
	embedComponentProps = {
		"name": "person"
	};
}

Angular + React + React Native

http://angularjs.blogspot.fr/2016/04/angular-2-react-native.html

OS (iOS/Android) + APIs

Native components + JS Bridge

React Native js components

Angular 2

wow

much native

Thanks :)

Using React inside an Angular app

By Florian Rival

Using React inside an Angular app

Talk at Angular Paris

  • 3,044