How to use React Web Components in Angular
How to use React Web Components in Angular - this is the second part of the article where we will learn how to use React Web Component in Angular
Howdy folks!! In the previous article we learned How to use Angular Web Components in React . In this tutorial we'll learn how to use A React component in an Angular Project 😎
We'll start with installing our angular project first then slowly install React dependencies and integrate our Components
1. Install Angular CLI if you don't have it already
npm install -g @angular/cli
2. Create a fresh new Angular Project
ng new my-angular-app
3. Add react
and react-dom
as dev dependency in your project
npm i --save -D @types/react @types/react-dom
You should find these new dependencies added to your project. The version can be a bit upgraded by the time you find this article. Feel free to leave a comment, I'll update this tutorial 😉
"dependencies": {
...
"react": "^17.0.2",
"react-dom": "^17.0.2",
...
},
"devDependencies": {
...
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
...
}
We need to add the following property in tsconfig.json
in our Angular project for typescript to recognize and compile React components
{
...
"jsx": "react",
...
}
4. Create our React component at the src directory of our angular project
CustomReactComponent.tsx
import * as React from 'react';
import { FunctionComponent, useEffect, useRef, useState } from 'react';
export interface IMyComponentProps {
counter: number;
onClick?: () => void;
}
export const CustomReactComponent: FunctionComponent<IMyComponentProps> = (props: IMyComponentProps) => {
const timerHandle = useRef<number | null>(null);
const [stateCounter, setStateCounter] = useState(42);
useEffect(() => {
timerHandle.current = +setInterval(() => {
setStateCounter(stateCounter + 1);
}, 2500);
return () => {
if (timerHandle.current) {
clearInterval(timerHandle.current);
timerHandle.current = null;
}
};
});
const {counter: propsCounter, onClick} = props;
const handleClick = () => {
if (onClick) {
onClick();
}
};
return (
<div>
<div>Props counter: {propsCounter}
<button type="button" onClick={handleClick}>click to increase</button>
</div>
<div>State counter: {stateCounter}</div>
</div>
);
};
Here stateCounter will trigger 2.5 sec after when the component loads and I define a function handleClick which I will operate through my Angular project.
5. Add a wrapper component to generate the web component
CustomReactComponentWrapper.tsx
import {
AfterViewInit,
Component,
ElementRef,
EventEmitter,
Input,
OnChanges,
OnDestroy,
Output,
SimpleChanges,
ViewChild,
ViewEncapsulation
} from '@angular/core';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { CustomReactComponent } from './CustomReactComponent';
const containerElementName = 'customReactComponentContainer';
@Component({
selector: 'app-my-component',
template: `<span #${containerElementName}></span>`,
// styleUrls: [''],
encapsulation: ViewEncapsulation.None,
})
export class CustomReactComponentWrapperComponent implements OnChanges, OnDestroy, AfterViewInit {
@ViewChild(containerElementName, { static: true }) containerRef!: ElementRef;
@Input() public counter = 10;
@Output() public componentClick = new EventEmitter<void>();
constructor() {
this.handleDivClicked = this.handleDivClicked.bind(this);
}
public handleDivClicked() {
if (this.componentClick) {
this.componentClick.emit();
this.render();
}
}
ngOnChanges(changes: SimpleChanges): void {
this.render();
}
ngAfterViewInit() {
this.render();
}
ngOnDestroy() {
ReactDOM.unmountComponentAtNode(this.containerRef.nativeElement);
}
private render() {
const { counter } = this;
ReactDOM.render(
<React.StrictMode>
<div>
<CustomReactComponent counter={counter} onClick={this.handleDivClicked} />
</div>
</React.StrictMode>
, this.containerRef.nativeElement);
}
}
Here I wrap the React component within a Angular Wrapper Component and generate the web component which I will use at my Angular project to generate the React instance.
6. Add the React web component to our angular web project
I am adding the component at app.component.html
for the sake of this tutorial, while working on an actual project you can use the React component within any Angular component in your entire application.
app.component.html
<div id="myReactComponentContainer">
<app-my-component [counter]="counter" (componentClick)="handleOnClick($event)"></app-my-component>
</div>
7. Now add the business logic and events at your app.component.ts
and your are all set.. 😁
export class AppComponent {
...
public counter = 21;
public handleOnClick(stateCounter: number) {
this.counter++;
}
}