https://d226lax1qjow5r.cloudfront.net/blog/blogposts/using-web-components-in-a-react-application-dr/Blog_WebComponents_React_1200x600.png

Utilisation de composants web dans une application React

Publié le May 10, 2021

Temps de lecture : 15 minutes

Dans un article précédentnous avons montré comment créer et publier un composant Web.

Il est maintenant temps de voir comment utiliser une des principales fonctionnalités des composants Web :

Les composants personnalisés et les widgets construits sur la base des normes des composants Web fonctionneront dans les navigateurs modernes et pourront être utilisés avec n'importe quelle bibliothèque JavaScript ou framework qui fonctionne avec HTML.

-WebComponents.org

Dans ce billet, nous allons voir comment les composants Web peuvent être intégrés dans un environnement React .

Compte API Vonage

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.

Composants Web

Tout d'abord, examinons les composants Web qui seront utilisés dans l'application.

Nous avons le composant clavier du billet précédent et un composant de liste de contacts. La liste de contacts peut enregistrer et charger les noms et les numéros de téléphone des personnes appelées à partir du stockage local du navigateur. Le composant Web peut également transmettre le numéro de téléphone d'un contact à l'application sous la forme d'un événement personnalisé lorsqu'il est cliqué.

Il existe également une boîte de dialogue Boîte de dialogue du composant Web matériel qui s'affichera après la fin d'un appel si le numéro n'est pas déjà dans les contacts, afin qu'il puisse être enregistré.

Demonstration of Web Components in a React application making a call and saving the contact

Enjeux

Pour voir quels obstacles nous pouvons rencontrer lors de l'utilisation de ces Applications Web dans une application React, nous allons référencer les éléments suivants. Des éléments personnalisés partout.

Ils ont pris la noble responsabilité de "S'assurer que les frameworks et les éléments personnalisés peuvent être BFFs 🍻".

Pour ce faire, nous prenons des frameworks/bibliothèques, nous les soumettons à différents tests et nous établissons un rapport sur la manière dont ils s'intègrent aux composants Web.

Comment React se positionne-t-il ? À la date de publication de ce billet, voici les résultats :

Results of using Web Components in a React application

La situation n'est pas brillante, mais nous pouvons la faire fonctionner. Jetons un coup d'œil à certains problèmes.

L'un des moyens de transmettre des données à votre composant Web est d'utiliser des propriétés :

<dwanes-keypad actionText="Call" cancelText="Hang up"></dwanes-keypad>

Lorsque cela est fait dans une Application React, les données sont stringifiées. Ainsi, les tableaux (ie [1,2,3,4]) se transformeront en "1,2,3,4" et les objets (ie {"key1":value1, "key2":value2}) deviendront le redoutable "[object Object]".

Un autre problème est la façon dont React gère les événements.

React a son SyntheticEvent qui est une enveloppe autour de l'événement natif d'un navigateur. Les conclusions de Custom Elements Everywhere montrent que le SyntheticEvent de React "ne peut pas écouter les événements DOM provenant des Custom Elements". Ils fournissent également une solution que nous allons voir par la suite.

Solutions

Maintenant que nous savons ce qui nous attend, travaillons à surmonter ces problèmes.

L'objectif est de créer un composant React "App" de base et de placer nos composants Web à l'intérieur.

Il existe deux façons d'écrire des composants dans une application React - en tant que Classe ou Fonction.

Auparavant, le fait de devoir utiliser "State" dans votre composant était un facteur déterminant pour l'utilisation d'un composant de classe. composant de classe plutôt qu'un composant de fonction.

Puis dans React 16.8, Hooks Ils vous permettent d'utiliser l'état et d'autres fonctionnalités de React sans écrire de classe.

Ainsi, pour être le plus exhaustif possible dans ce post, nous inclurons les composants Web dans les applications React qui sont créées à l'aide de composants de classe et de composants de fonction avec des Hooks.

Comme à chaque fois que des composants Web sont utilisés, ils doivent être inclus dans le projet. Vous pouvez soit les installer, soit créer un lien vers eux à partir d'un CDN. (Ce point a été abordé dans le article précédent.)

Pour cette intégration, nous utiliserons un CDN.

Dans l'étiquette <head> de public\index.html dans le code d'exemple, vous trouverez :

<!-- 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>

Composante de la classe

Vous pouvez trouver l'exemple de code dans ce projet Glitch.

Note : J'ai remixé le Modèle de démarrage Glitch React.

Gestion des événements

Pour pouvoir gérer les événements provenant d'un composant Web, nous devons d'abord obtenir une référence à celui-ci afin que React sache qu'il existe et puisse ajouter un écouteur d'événements. Dans la fonction src\App.js render, vous trouverez quelques 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>

Les balises ref indiquent à React qu'il doit prêter attention à ces éléments.

Dans le componentDidMount() dans src\App.jsles auditeurs d'événements sont ajoutés aux références d'éléments que nous venons de mettre en place. Voici le 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);
});

Traitement des données

Pour notre composant clavier, nous passons des chaînes dans les propriétés, donc rien de spécial ne doit être fait avec ces données dans React.

Lors de l'enregistrement du contact après un appel, les données sont des objets :

{name:this.refs.firstName.value, phone:this.state.numberToSave}

Elle est transmise à une méthode du composant Web de la liste des contacts :

this.refs.contacts.saveContact({name:this.refs.firstName.value, phone:this.state.numberToSave});

Si le composant liste de contacts n'utilisait pas l'objet pour manipuler les données et les enregistrer dans le stockage local, nous pourrions passer l'objet comme suit :

this.refs.contacts.contactProp = {name:this.refs.firstName.value, phone:this.state.numberToSave};

Il en va de même pour les tableaux.

Remarque importante ! L'API utilisée pour obtenir la référence aux composants Web est considérée comme ancienne et est "susceptible d'être supprimée dans l'une des prochaines versions". documentation contient plus d'informations et propose des alternatives.

Montrons l'une des alternatives mentionnées.

Si vous utilisez React 16.3 ou une version ultérieure, voici le projet Glitch exemple de code en utilisant React.createRef().

C'est à peu près la même idée, mais avec plus de syntaxe. Vous créez la référence avec React.createRef() dans le constructeur :

this.contacts = React.createRef();

Attachez-la au composant Web dans la section render:

<dwanes-contacts ref={this.contacts}></dwanes-contacts>

Ajouter un écouteur d'événement dans componentDidMount():

this.contacts.current.addEventListener('contact-selected', (event) => {
  this.keypad.current.setDigits(event.detail.contact.phone);
});

Appeler une méthode d'un composant Web :

this.contacts.current.saveContact({name:this.firstName.current.value, phone:this.state.numberToSave});

Transmettre des données "riches" au composant Web :

this.contacts.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};

this.contacts.current.arrayProp = [value1, value2, value3];

Composant de fonction avec crochets

Maintenant, pour la nouvelle façon, à partir de React 16.8, qui peut être utilisée pour créer une référence de composant Web.

La plupart des tâches lourdes sont gérées par les Hooks. Qu'il s'agisse de gérer l'état, les effets de bord ou les références DOM, il y a probablement un Hook que vous pouvez utiliser.

Si ce n'est pas le cas, vous pouvez créer un crochet personnalisé.

Dans ce cas, l'un des crochets que nous utiliserons est useRef.

Cela ressemblera beaucoup à l'exemple React.createRef() exemple.

Vous pouvez trouver l'exemple de code Function Component with Hooks dans ce projet Glitch.

Gestion des événements

Tout d'abord, nous devons initialiser les références de chaque composant Web. C'est ce que nous faisons avec ce code :

const keypad = useRef(null);
const dialog = useRef(null);
const contactsEl = useRef(null);
const firstName = useRef(null);

null est la valeur initiale de la référence.

Ensuite, dans la section de retour, nous attachons les références aux composants Web avec la balise ref={referenceName}.

Voici le 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>

Ajoutons maintenant nos récepteurs d'événements.

Pour ce faire, nous les placerons dans un crochet de type 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);
    };
});

Traitement des données

Comme nous l'avons déjà mentionné, ce code ressemblera beaucoup à l'exemple de code React.createRef() exemple de code.

Utilisation de la méthode d'un composant Web pour envoyer des données :

contactsEl.current.saveContact({name:firstName.current.value, phone:numberToSave});

Pour transmettre des données "riches" au composant Web :

contactsEl.current.contactProp = {name:this.firstName.current.value, phone:this.state.numberToSave};

contactsEl.current.arrayProp = [value1, value2, value3];

Passer un appel

Nous avons accroché nos Web Components, pourquoi ne pas passer un appel avec notre application React ?

Les étapes ci-dessous sont une version modifiée et un aperçu rapide de notre tutoriel sur la création d'un appel vocal in-app. tutoriel pour utiliser nos composants Web.

Vous pouvez vous y référer pour plus de détails.

Pour le faire fonctionner, il faut

Étape 1 : Remixer ce projet Glitch.

Cela permettra non seulement de configurer l'application React avec les Web Components, mais aussi d'installer le Client SDK Nexmo qui sera utilisé pour passer l'appel téléphonique.

Etape 2 : Installer l'outil CLI de Nexmo : Installer l'outil Nexmo CLI.

Dans votre terminal, tapez :

npm install nexmo-cli@beta -g

Obtenez votre clé d'API de développeur Vonage et votre secret d'API à partir de votre tableau de bord.

Exécutez la commande suivante dans un terminal, en remplaçant api_key et api_secret par les vôtres :

nexmo setup api_key api_secret

Étape 3 : Créer un OCNI.

Assurez-vous d'être connecté à GitHub puis allez sur https://gist.github.com .

Entrer ncco.json dans "Nom de fichier, y compris l'extension".

Copiez et collez l'objet JSON suivant dans le gist :

[
    {
        "action": "talk",
        "text": "Please wait while we connect you."
    },
    {
        "action": "connect",
        "endpoint": [
            {
                "type": "phone",
                "number": "PHONE_NUMBER"
            }
        ]
    }
]

Remplacer PHONE_NUMBER par votre numéro de téléphone. Les numéros Numbers sont au format E.164, les "+" et "-" ne sont pas valables. Veillez à préciser l'indicatif de votre pays lorsque vous saisissez votre numéro, par exemple, US : 14155550100 et UK : 447700900001.

Cliquez sur le bouton Create secret gist sur le bouton

Cliquez sur le bouton Raw sur le bouton

Notez l'URL qui s'affiche dans votre navigateur, vous l'utiliserez à l'étape suivante.

Étape 4 : Créer une application Nexmo

Créez votre répertoire de projet si vous ne l'avez pas encore fait.

mkdir web-components-react

Allez dans le répertoire du projet.

cd web-components-react

Créez une application Nexmo en copiant et en collant la commande ci-dessous dans le terminal :

Veillez à modifier la valeur de l'argument --voice-answer-url en remplaçant GIST-URL par l'URL gist de l'étape précédente.

nexmo app:create "App to Phone Tutorial" --capabilities=voice --keyfile=private.key --voice-event-url=https://example.com/ --voice-answer-url=GIST-URL

Un fichier nommé .nexmo-app est créé dans le répertoire de votre projet et contient l'identifiant de l'application Nexmo nouvellement créée et la clé privée. Un fichier de clé privée nommé private.key est également créé.

Veuillez noter l'identifiant de l'application car vous en aurez besoin à l'avenir.

Étape 5 : Créer un utilisateur

Créez un utilisateur nommé Alice à l'aide de la commande suivante dans l'interface de commande Nexmo :

nexmo user:create name="Alice"

Cela renverra un identifiant similaire à celui qui suit :

User created: USR-aaaaaaaa-bbbb-cccc-dddd-0123456789ab

Étape 6 : Générer un JWT

Générez un JWT à l'aide de la CLI Nexmo en exécutant la commande suivante, mais n'oubliez pas de remplacer la variable APP_ID par votre propre valeur :

nexmo jwt:generate ./private.key exp=$(($(date +%s)+21600)) acl='{"paths":{"/*/users/**":{},"/*/conversations/**":{},"/*/sessions/**":{},"/*/devices/**":{},"/*/image/**":{},"/*/media/**":{},"/*/push/**":{},"/*/knocking/**":{},"/*/legs/**":{}}}' sub=Alice application_id=APP_ID

Le JWT généré sera valide pour les 6 prochaines heures.

Copiez et collez le JWT dans le fichier de projet src/App.js dans le fichier du projet Glitch, à l'endroit où il est indiqué "PASTE ALICE JWT HERE".

Étape 7 : Appelez vous-même !

Composez votre numéro sur le clavier et appuyez sur APPEL.

Si tout a fonctionné correctement, votre téléphone devrait recevoir un appel. Une fois l'appel terminé, une boîte de dialogue doit apparaître pour vous demander si vous souhaitez enregistrer le numéro.

Remarque : le NCCO étant codé en dur avec votre numéro de téléphone, votre numéro sera appelé, quelle que soit la manière dont vous l'avez tapé au clavier. Pour générer dynamiquement le NCCO, il faudra le faire en amont.

Voilà, c'est fait ! Nous avons maintenant utilisé les composants Web dans une application React.

Cela a-t-il fonctionné ? C'était cool ?

Comme pour tout ce qui concerne le codage, il existe de multiples façons de faire les choses.

J'ai trouvé un autre moyen dans la base de données React et Stencil JS est d'envelopper vos composants Web dans des composants React.

Avez-vous procédé de cette manière ou peut-être d'une autre manière ? Nous aimerions vraiment en savoir plus sur ce sujet ou sur tout autre commentaire ou question dans notre canal Slack de la communauté.

Partager:

https://a.storyblok.com/f/270183/384x384/1a06993970/dwanehemmings.png
Dwane HemmingsDéveloppeur JavaScript Advocate