This projects aims to use React Components inside an Angular project. The project is based on Microsoft's react-angular project (Github).
Angular Host: (Github repo)
An Angular project that hosts both React components and Angular components. The angular components are based on Angular io's example project
Thin Wrapper: (Github repo, npm package)
A thin wrapper for the React components that maps inputs and outputs between the host Angular component and the child React component.
React Component: (Github repo, npm package)
A sample React project that can be used as a standalone project, hosted inside another React project or hosted inside an Angular project using the Wrapper.
The thin wrapper maps the inputs and outputs (callbacks) passed from the Angular application to the React component, which allows seamless integration.
Props are passed down from the Angular host to the React component in real time.
Callbacks are invoked from the React component and pass events to the Angular host.
There are two approaches for state management
-
The redux store is persisted throughout Angular navigation (store is persisted, root React component is unmounted and remounted on navigation from an Angular component)
-
The Angular host can handle state management by passing down props, and the React component passing events up to the Angular host using callbacks. This approach has the drawback of having the two projects closely coupled.
We use the former approach in this project, since having the React component as a standalone self contained project was a goal of this POC.
There are two approaches to route handling from withing the React component
-
Routing will work normally for the React component, however Angular needs to be aware of all routes used by the React component in order for history and direct navigation to work (Implementation). Using this method navigation from a React component to an Angular component is not possible.
-
A callback that is responsible for navigation is passed from the Angular host to the react component. The drawback of this method that on each navigation the root React component will be unmounted and remounted (might cause performance issues).
We use both approaches in this project the former method for internal navigation between React components and the latter for navigation from a React component to an Angular component.
react-angular project provides benchmarks (link)
Install packages then run
yarn
yarn start
or
npm install
npm start
These steps are already implented in this project. This is a walkthrough of these steps
Install angular-react, react, react-dom
yarn add @angular-react/core react react-dom @types/react @types/react-dom
or
npm install @angular-react/core react react-dom @types/react @types/react-dom
Install the React project and the wrapper in our case poc-react-app (React application) and poc-react-components (wrapper)
There are multiple approaches to installing the modules
Currently the npm registry is used, Nexus 3 or other registries are also possible (by specifying the registry in .npmrc / .yarnrc)
Currently
yarn add poc-react-app poc-react-components
Currently
yarn add https://github.com/AndrewMagdy/thin-wrapper#poc-react-components-v0.1.3-gitpkg https://github.com/AndrewMagdy/poc-react-app
In Angular’s project app.module import the AngularReactBrowserModule from @angular-react/core and use it instead of Angular’s Browser module
import { AngularReactBrowserModule } from "@angular-react/core";
...
@NgModule({
imports: [
AngularReactBrowserModule,
....
]
})
],
In Angular's project app.module import the wrapper and add it in Ngmodule imports
import { PocAppModule } from "poc-react-components";
...
@NgModule({
imports: [
...
PocAppModule,
...
],
Add the react component (imported in the above step from the wrapper) to the desired angular component using its selector ( in our case), props can be passed to the React component, using normal Angular syntax
-----------dashboard.component.html-----------
<poc-app-react
//Prop passed to the React component in real time.
[angularTestProp]="angularTestProp"
//Callback to handle navigation by the Angular application
(angularNavigateTo)="navigateTo($event)"
//Callback invoked by the React component on state change
(onStateChange)="onStateChange($event)"
>
</poc-app-react>
-----------dashboard.component.ts-----------
angularTestProp = "Hello World";
reactState = {};
onStateChange(state): void {
this.reactState = state;
}
navigateTo(route): void {
this.router.navigateByUrl(route);
}
Add all the routes that the React component can navigate to to the Angular routing module so that they point to an Angular component that hosts the React component (Like the one created in the above step)
const routes: Routes = [
.....
//Dashboard component hosts the react component
//dashboard, items and basked are all routes used by the React component
{ path: "dashboard", component: DashboardComponent },
{ path: "items", component: DashboardComponent },
{ path: "basket", component: DashboardComponent },
.....
];