
Verwendung von Webkomponenten in einer React-Anwendung
Lesedauer: 14 Minuten
In einem früheren Beitraghaben wir Ihnen gezeigt, wie Sie eine Webkomponente erstellen und veröffentlichen können.
Jetzt ist es an der Zeit zu sehen, wie man eine der wichtigsten Funktionen von Web Components nutzt:
Benutzerdefinierte Komponenten und Widgets, die auf den Web Component-Standards basieren, funktionieren in allen modernen Browsern und können mit jeder JavaScript-Bibliothek oder jedem Framework verwendet werden, das mit HTML arbeitet.
In diesem Beitrag sehen wir uns an, wie Webkomponenten in eine React Anwendung integriert werden können.
Vonage API-Konto
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
In diesem Lernprogramm wird auch eine virtuelle Telefonnummer verwendet. Um eine zu erwerben, gehen Sie zu Rufnummern > Rufnummern kaufen und suchen Sie nach einer Nummer, die Ihren Anforderungen entspricht.
Web-Komponenten
Werfen wir zunächst einen Blick auf die Webkomponenten, die in der Anwendung verwendet werden sollen.
Wir haben die Tastenkomponente aus dem vorherigen Beitrag und eine Komponente für die Kontaktliste. Die Kontaktliste kann die Namen und Telefonnummern von Personen speichern und laden, die aus dem lokalen Speicher des Browsers lokalen Speicher. Die Webkomponente kann auch die Telefonnummer eines Kontakts als benutzerdefiniertes Ereignis an die Anwendung weitergeben, wenn sie angeklickt wird.
Außerdem gibt es einen Material-Webkomponente-Dialog der nach Beendigung eines Anrufs angezeigt wird, wenn die Nummer noch nicht in den Kontakten enthalten ist, damit sie gespeichert werden kann.

Ausgaben
Um zu sehen, auf welche Hürden wir bei der Verwendung dieser Webkomponenten in einer React-Anwendung stoßen können, verweisen wir auf Überall benutzerdefinierte Elemente.
Sie haben die ehrenvolle Aufgabe übernommen, dafür zu sorgen, dass Frameworks und benutzerdefinierte Elemente beste Freunde sein können 🍻".
Dazu werden Frameworks/Bibliotheken verschiedenen Tests unterzogen, und es wird ein Bericht über die Ergebnisse erstellt, wie gut sie sich in Webkomponenten integrieren lassen.
Wie schneidet React also ab? Zum Zeitpunkt der Veröffentlichung dieses Beitrags sind hier die Ergebnisse:

Es sieht nicht gut aus, aber wir können es hinbekommen. Werfen wir einen Blick auf einige der Probleme.
Eine Möglichkeit, Daten an Ihre Webkomponente zu übergeben, sind Eigenschaften:
<dwanes-keypad actionText="Call" cancelText="Hang up"></dwanes-keypad>
Wenn dies in einer React-Anwendung geschieht, werden die Daten in Strings umgewandelt. Die Übergabe von Arrays (z.B. [1,2,3,4]) wird also zu "1,2,3,4" und Objekte (z.B. {"key1":value1, "key2":value2}) werden zu dem gefürchteten "[object Object]".
Ein weiteres Problem ist, wie React Ereignisse behandelt.
React hat seine SyntheticEvent Instanz, die ein Wrapper um das native Ereignis eines Browsers ist. Die Ergebnisse von Custom Elements Everywhere zeigen, dass Reacts SyntheticEvent "nicht auf DOM-Ereignisse von Custom Elements hören kann". Sie bieten auch eine Lösung an, die wir uns als nächstes ansehen werden.
Lösungen
Da wir nun wissen, was auf uns zukommt, sollten wir daran arbeiten, diese Probleme zu überwinden.
Der Plan ist, eine grundlegende React "App"-Komponente zu erstellen und dann unsere Webkomponenten darin zu platzieren.
Es gibt zwei Möglichkeiten, Komponenten in einer React-Anwendung zu schreiben - als Klasse oder Funktion.
Früher war die Notwendigkeit, "State" in Ihrer Komponente zu verwenden, ein entscheidender Faktor dafür, ob Sie eine Klassenkomponente gegenüber einer Funktionskomponente.
Dann in React 16.8, Hooks eingeführt: "Mit ihnen kann man Zustände und andere React-Funktionen nutzen, ohne eine Klasse zu schreiben."
Um also so gründlich wie möglich zu sein, werden wir in diesem Beitrag Webkomponenten in React-Anwendungen einbeziehen, die mit Klassenkomponenten und Funktionskomponenten mit Hooks erstellt werden.
Wie immer, wenn Webkomponenten verwendet werden, müssen sie in das Projekt eingebunden werden. Sie können sie entweder installieren oder von einem CDN auf sie verlinken. (Dies wurde in dem vorherigen Beitrag.)
Für diese Integration werden wir die Daten von einem CDN beziehen.
Im <head> Tag der public\index.html Datei im Beispielcode finden Sie:
<!-- Web Component polyfill -->
<script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script>
<!-- Load the Web Components -->
<script type="module" src="https://unpkg.com/@material/mwc-dialog@canary/mwc-dialog?module"></script>
<script type="module" src="https://unpkg.com/@dwane-vonage/dwanes-keypad@latest/dwanes-keypad.js?module"></script>
<script type="module" src="https://unpkg.com/@dwane-vonage/dwanes-contacts@latest/dwanes-contacts.js?module"></script> Klassenkomponente
Sie finden den Beispielcode in diesem Glitch-Projekt.
Anmerkung: Ich habe die Glitch React Starter Vorlage.
Umgang mit Ereignissen
Um mit den Ereignissen einer Webkomponente umgehen zu können, müssen wir zunächst einen Verweis auf sie erhalten, damit React weiß, dass sie existiert und einen Ereignis-Listener hinzufügen kann. In der src\App.js render Funktion, finden Sie einige ref Tags:
<main>
<section>
<dwanes-keypad actionText="Call" cancelText="Hang up" ref="keypad"></dwanes-keypad>
<div id="status">{this.state.callStatus}</div>
</section>
<dwanes-contacts ref="contacts"></dwanes-contacts>
</main>
<mwc-dialog id="dialog" heading="Contacts" ref="dialog">
<p>Save <span id="number-to-save">{this.state.numberToSave}</span> to contacts?</p>
<mwc-textfield
id="text-field"
minlength="3"
maxlength="64"
placeholder="First name"
dialogInitialFocus
required
ref="firstName">
</mwc-textfield>
<mwc-button
id="primary-action-button"
slot="primaryAction"
onClick={this.handleSaveContact}>
Confirm
</mwc-button>
<mwc-button
slot="secondaryAction"
dialogAction="close">
Cancel
</mwc-button>
</mwc-dialog>
Die ref Tags lassen React wissen, dass diese Elemente zu beachten sind.
In der componentDidMount() in src\App.jswerden die Ereignis-Listener zu den Elementreferenzen hinzugefügt, die wir gerade eingerichtet haben. Hier ist der Code:
this.refs.contacts.addEventListener('contacts-loaded', (event) => {
contacts = event.detail.contacts;
console.log('contacts-loaded: ', contacts);
});
this.refs.contacts.addEventListener('contact-selected', (event) => {
this.refs.keypad.setDigits(event.detail.contact.phone);
});
this.refs.keypad.addEventListener('action-ended', () => {
this.setState({callStatus: "Call has ended."});
const contactFound = contacts.find(contact => contact.phone === this.state.numberToSave);
if (contactFound){
console.log('Number already in contacts')
} else {
this.refs.dialog.show();
}
});
this.refs.keypad.addEventListener('digits-sent', event => {
if (event.detail.digits !== ""){
this.refs.keypad.createAction();
this.setState({callStatus: "Call is being made", numberToSave:event.detail.digits});
} else {
this.setState({callStatus: "Please enter a phone number."});
}
});
this.refs.keypad.addEventListener("digit-added", event => {
console.log('digit-added: ', event.detail.digit);
});
Umgang mit Daten
Für unsere Tastaturkomponente übergeben wir Strings in die Eigenschaften, so dass nichts Besonderes mit diesen Daten in React gemacht werden muss.
Wenn Sie den Kontakt nach einem Anruf speichern, sind die Daten ein Objekt:
{name:this.refs.firstName.value, phone:this.state.numberToSave}Diese wird an eine Methode in der Webkomponente Kontaktliste übergeben:
this.refs.contacts.saveContact({name:this.refs.firstName.value, phone:this.state.numberToSave});Wenn die Komponente "Kontaktliste" das Objekt nicht zur Bearbeitung der Daten und zur Speicherung im lokalen Speicher verwenden würde, könnten wir das Objekt wie folgt übergeben:
this.refs.contacts.contactProp = {name:this.refs.firstName.value, phone:this.state.numberToSave};Das Gleiche gilt für Arrays.
Wichtiger Hinweis! Die API, die verwendet wird, um den Verweis auf die Webkomponenten zu erhalten, gilt als veraltet und wird "wahrscheinlich in einer der zukünftigen Versionen entfernt werden". Dokumentation enthält weitere Informationen und bietet Alternativen.
Lassen Sie uns eine der genannten Alternativen aufzeigen.
Wenn Sie React 16.3 oder höher verwenden, finden Sie hier das Glitch-Projekt Beispielcode unter Verwendung von React.createRef().
Ziemlich genau die gleiche Idee, nur mehr Syntax. Sie erzeugen die Referenz mit React.createRef() im Konstruktor:
this.contacts = React.createRef();Hängen Sie es an die Webkomponente in der render:
<dwanes-contacts ref={this.contacts}></dwanes-contacts>
Hinzufügen eines Ereignis-Listeners in componentDidMount():
this.contacts.current.addEventListener('contact-selected', (event) => {
this.keypad.current.setDigits(event.detail.contact.phone);
});
Rufen Sie die Methode einer Webkomponente auf:
this.contacts.current.saveContact({name:this.firstName.current.value, phone:this.state.numberToSave});Übergeben Sie "reiche" Daten an die Webkomponente:
this.contacts.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};
this.contacts.current.arrayProp = [value1, value2, value3]; Funktionskomponente mit Häkchen
Nun zum neuesten Weg, ab React 16.8, der verwendet werden kann, um eine Web Component-Referenz zu erstellen.
Ein großer Teil der schweren Arbeit wird mit Hooks erledigt. Ob es sich um die Handhabung von Status, Seiteneffekten oder DOM-Referenzen handelt, es gibt wahrscheinlich eine Hook, die Sie verwenden können.
Falls nicht, können Sie einen benutzerdefinierten Hook erstellen.
In diesem Fall ist einer der Hooks, die wir verwenden werden useRef.
Dies wird ähnlich aussehen wie im React.createRef() Beispiel.
Den Beispielcode der Funktionskomponente mit Hooks finden Sie in diesem Glitch-Projekt.
Umgang mit Ereignissen
Zunächst müssen wir die Referenzen für jede Webkomponente initialisieren. Das geschieht mit diesem Code:
const keypad = useRef(null);
const dialog = useRef(null);
const contactsEl = useRef(null);
const firstName = useRef(null);null ist der Ausgangswert für die Referenz.
Im Rückgabeabschnitt fügen wir dann die Verweise auf die Webkomponenten mit dem ref={referenceName}.
Hier ist der Code:
<main>
<section>
<dwanes-keypad actionText="Call" cancelText="Hang up" ref={keypad}></dwanes-keypad>
<div id="status">{callStatus}</div>
</section>
<dwanes-contacts ref={contactsEl}></dwanes-contacts>
</main>
<mwc-dialog id="dialog" heading="Contacts" ref={dialog}>
<p>Save <span id="number-to-save">{numberToSave}</span> to contacts?</p>
<mwc-textfield
id="text-field"
minlength="3"
maxlength="64"
placeholder="First name"
dialogInitialFocus
required
ref={firstName}>
</mwc-textfield>
<mwc-button
id="primary-action-button"
slot="primaryAction"
onClick={handleSaveContact}>
Confirm
</mwc-button>
<mwc-button
slot="secondaryAction"
dialogAction="close">
Cancel
</mwc-button>
</mwc-dialog>
Fügen wir nun unsere Ereignis-Listener hinzu.
Zu diesem Zweck verpacken wir sie in einen useEffect Hook:
useEffect(()=> {
contactsEl.current.addEventListener('contacts-loaded', handleContactsLoaded);
contactsEl.current.addEventListener('contact-selected', handleContactSelected);
keypad.current.addEventListener('digit-added', handleDigitAdded);
keypad.current.addEventListener('digits-sent', handleDigitsSent);
keypad.current.addEventListener('action-ended', handleActionEnded);
return () => {
contactsEl.current.removeEventListener('contacts-loaded', handleContactsLoaded);
contactsEl.current.removeEventListener('contact-selected', handleContactSelected);
keypad.current.removeEventListener('digit-added', handleDigitAdded);
keypad.current.removeEventListener('digits-sent', handleDigitsSent);
keypad.current.removeEventListener('action-ended', handleActionEnded);
};
});
Umgang mit Daten
Wie bereits erwähnt, wird dies sehr ähnlich aussehen wie der React.createRef() Beispielcode.
Verwendung einer Methode einer Webkomponente zum Senden von Daten:
contactsEl.current.saveContact({name:firstName.current.value, phone:numberToSave});Zur Übergabe von "reichen" Daten an die Webkomponente:
contactsEl.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};
contactsEl.current.arrayProp = [value1, value2, value3]; Anrufen
Wir haben unsere Web-Komponenten eingerichtet, warum rufen wir nicht mit unserer React-Anwendung an?
Die folgenden Schritte sind eine modifizierte Version und ein kurzer Überblick über unser Tutorial zum Tätigen eines In-App-Anrufs Tutorials zur Verwendung unserer Webkomponenten.
Darin können Sie weitere Einzelheiten nachlesen.
Um es zum Laufen zu bringen, ist Folgendes erforderlich:
Die Nexmo CLI
Ein GitHub-Konto
Schritt 1: Remixen Sie dieses Glitch-Projekt.
Dadurch wird nicht nur die React-Anwendung mit den Web Components eingerichtet, sondern auch das Nexmo Client SDK installiert, das für den Telefonanruf verwendet werden soll.
Schritt 2: Installieren Sie das Nexmo CLI-Tool.
Geben Sie in Ihrem Terminal ein:
Rufen Sie Ihren Vonage Entwickler-API-Schlüssel und Ihr API-Geheimnis über Ihr Dashboard.
Führen Sie den folgenden Befehl in einem Terminal aus und ersetzen Sie dabei api_key und api_secret durch Ihre eigenen:
Schritt 3: Erstellen Sie eine NCCO.
Stellen Sie sicher, dass Sie angemeldet sind bei GitHub und gehen Sie dann auf https://gist.github.com.
Geben Sie ncco.json in "Dateiname mit Erweiterung" ein.
Kopieren Sie das folgende JSON-Objekt und fügen Sie es in die Gist ein:
[
{
"action": "talk",
"text": "Please wait while we connect you."
},
{
"action": "connect",
"endpoint": [
{
"type": "phone",
"number": "PHONE_NUMBER"
}
]
}
]Ersetzen Sie PHONE_NUMBER durch Ihre Rufnummer. Nexmo-Nummern sind im E.164-Format, "+" und "-" sind nicht gültig. Vergewissern Sie sich, dass Sie Ihre Landesvorwahl angeben, wenn Sie Ihre Nummer eingeben, zum Beispiel US: 14155550100 und UK: 447700900001.
Klicken Sie auf die Create secret gist Schaltfläche.
Klicken Sie auf die Raw Schaltfläche.
Notieren Sie sich die URL, die in Ihrem Browser angezeigt wird, denn Sie werden sie im nächsten Schritt verwenden.
Schritt 4: Erstellen einer Nexmo-Anwendung
Erstellen Sie Ihr Projektverzeichnis, falls Sie dies noch nicht getan haben.
Wechseln Sie in das Projektverzeichnis.
Erstellen Sie eine Nexmo-Anwendung, indem Sie den folgenden Befehl kopieren und im Terminal einfügen:
Stellen Sie sicher, dass Sie den Wert von
--voice-answer-urlArgument durch Ersetzen vonGIST-URLdurch die Gist-URL aus dem vorherigen Schritt ersetzen.
Eine Datei namens .nexmo-app wird in Ihrem Projektverzeichnis erstellt und enthält die neu erstellte Nexmo Application ID und den privaten Schlüssel. Eine private Schlüsseldatei namens private.key wird ebenfalls erstellt.
Bitte notieren Sie sich die Anwendungs-ID, da Sie diese in Zukunft benötigen werden.
Schritt 5: Einen Benutzer anlegen
Erstellen Sie einen Benutzer namens Alice mit folgendem Befehl über die Nexmo CLI:
Das Ergebnis ist eine Benutzer-ID ähnlich der folgenden:
User created: USR-aaaaaaaa-bbbb-cccc-dddd-0123456789ab
Schritt 6: Erzeugen eines JWT
Generieren Sie ein JWT mit der Nexmo CLI, indem Sie den folgenden Befehl ausführen, aber denken Sie daran, die Variable APP_ID Variable durch Ihren eigenen Wert zu ersetzen:
Der generierte JWT ist für die nächsten 6 Stunden gültig.
Kopieren Sie die JWT und fügen Sie sie in die src/App.js Glitch-Projektdatei ein, wo es heißt "PASTE ALICE JWT HERE".
Schritt 7: Rufen Sie selbst an!
Wählen Sie Ihre Nummer auf dem Ziffernblock und drücken Sie ANRUF.
Wenn alles richtig funktioniert hat, sollte Ihr Telefon einen Anruf erhalten. Nach Beendigung des Anrufs sollte ein Dialogfeld erscheinen, in dem Sie gefragt werden, ob Sie die Nummer speichern möchten.
Hinweis: Da die NCCO mit Ihrer Telefonnummer fest codiert ist, wird Ihre Nummer unabhängig von der Eingabe auf der Tastatur angerufen. Um die NCCO dynamisch zu generieren, muss dies im Backend erfolgen.
Nun, das war's! Wir haben jetzt Webkomponenten in einer React-Anwendung verwendet.
Hat es funktioniert? War es cool?
Wie bei allem, was mit Programmierung zu tun hat, gibt es mehrere Möglichkeiten, etwas zu tun.
Eine andere Möglichkeit habe ich in der React und Stencil JS Dokumentation gefunden habe, ist es, Ihre Webkomponenten in React-Komponenten zu verpacken.
Haben Sie es auf diese Weise oder vielleicht anders gemacht? Wir würden uns freuen, wenn Sie uns Ihre Meinung dazu oder andere Kommentare und Fragen in unserem Slack-Kanal der Gemeinschaft.
