Using AngularJS components in React 😈
We’ve seen some informative articles on how to use React components inside an Angular app, but guides for “using Angular components inside React” were scarce. (Reasons for migrating to React at all, and to React instead of Angular 2+ are out of scope of this article and have by extensively covered by other articles and this chart of download trends for the libraries)
The GDC project was in the process of migrating from AngularJS (Angular 1) to React. For quite a while, the React-in-Angular pattern was used to perform a strangler migration one component at a time. As React ate through more and more of the project, we reached a tipping point where it could become the root app, but we were still short a few features that prevented us from reaching parity.
Being able to reuse those Angular components as-is allowed us to continue the migration without compromising existing features or our delivery timeline.
This part is actually incredibly simple.
Assuming the name of the root module for your legacy Angular app is
ngApp, and the name of the Angular component you want to wrap as a react component is
Here’s a contrived example using angular-bootstrap-datetimepicker
This would suffice for completely self-contained components/directives, but what if there are buttons or links in the Angular component that are supposed to take the user to the now react app?
Assuming ui-router is being used for routing, we only have to intercept calls to
You can then choose how the app should handle those requests
Here’s an example that passes it off to react-router v4
If the old routes and new routes don’t match 1:1, you could insert a mapping function that maps old routes to new routes. An example of that can be found in our codebase here
Neutralize Angular’s location tampering
A problem we ran into was that after initializing and then navigating away from the Angular component, the browser’s address bar would become “stuck”, always resetting to the route the angular component was on.
Keep an eye on the address bar:
It turns out Angular’s digest cycle checks the browser’s location, and when it notices that the browser’s url is different from what it thinks it should be, it sets the browser’s url to the “correct” value. Since the url is now being handled outside of Angular, we need to disable this behaviour.
Looking at Angular’s source, we see it sets the url via the (🕵️private)
$browser service. Here’s how to neutralize that:
This overrides angular’s url method and change handler with a no-op
We’re nearly done, just need to clean up the bootstrapped angular app when the React component unmounts.
Here’s a minimal example (you can replace
ngApp with the name of your angular module).
It’s always a difficult decision on whether, when, and how to migrate from a framework. For those that have started or are about to begin, I hope this article will help ease and complete that transition.
Originally published at softeng.oicr.on.ca on April 17, 2017
Edited with updates June 2017