Thomas Derflinger Blog

Composants Web de LitElement dans l'application React

LitElement est une bibliothèque de composants Web de Google. Elle succède à la bibliothèque Polymer et vise la rapidité et la compatibilité avec le standard Web Components. Comment intégrer les LitElements dans votre application React et utiliser la gestion des événements c’est que je veux montrer dans cet article.

L’application finale peut être téléchargée à partir de mon dépôt GitHub (https://github.com/tderflinger/react-litelement-example).

À propos de LitElement

LitElement, avec lit-html, forment le dernier cycle des bibliothèques de Google qui adhèrent à la norme des composants Web.

Les composants Web vous permettent d’étendre le HTML et sont pris en charge par tous les les navigateurs. Pour les anciens navigateurs, il existe des bibliothèques de polyfill.

La décomposition de votre application en ces éléments de base la rend plus faciles à entretenir et plus réutilisables.

Si le concept de composants Web semble familier aux développeurs de React, il l’est. Dans les applications React, les programmeurs créent également des composants, mais la technologie derrière les deux est différent.

Néanmoins, vous pouvez utiliser les composants Web LitElement dans votre application React.

Préparation de l’application React

Comme point de départ de l’exemple, j’ai créé une nouvelle application React avec Create React App. Afin d’utiliser LitElement et lit-html, j’ajoute les deux bibliothèques :

yarn add lit-element lit-html --save

Ensuite, parce que l’exemple LitElement utilise des décorateurs JavaScript, j’ajoute react-app-rewired et la proposition de décorateurs Babel (@babel/plugin-proposal-decorators).

Vous pouvez suivre la procédure décrite dans l’article de Michiel Sikma.

Intégrer un LitElement

L’exemple de LitElement que j’utilise est le bouton-poussoir Wokwi. Il a été développé par Uri Shaked dans le cadre de son projet Wokwi de pièces électroniques Arduino en JavaScript.

J’ai adapté un peu le pushbutton-element.js mais j’ai laissé la fonctionnalité essentiellement inchangée.

pushbutton-element.js, adapté

import { css, customElement, html, LitElement, property } from 'lit-element';
import { SPACE_KEYS } from './utils/keys';

@customElement('wokwi-pushbutton')
class PushbuttonElement extends LitElement {
  @property() color = 'red';
  @property() pressed = false;

  static get styles() {
    return css`
      button {
        border: none;
        background: none;
        padding: 0;
        margin: 0;
        text-decoration: none;
        -webkit-appearance: none;
        -moz-appearance: none;
      }

      button:active .button-circle {
        fill: url(#grad-down);
      }

      .clickable-element {
        cursor: pointer;
      }
    `;
  }

  render() {
    const { color } = this;
    return html`
      <button
        aria-label="${color} pushbutton"
        @mousedown=${this.down}
        @mouseup=${this.up}
        @touchstart=${this.down}
        @touchend=${this.up}
        @keydown=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.down()}
        @keyup=${(e: KeyboardEvent) => SPACE_KEYS.includes(e.key) && this.up()}
      >
        <svg
          width="18mm"
          height="12mm"
          version="1.1"
          viewBox="-3 0 18 12"
          xmlns="http://www.w3.org/2000/svg"
          xmlns:xlink="http://www.w3.org/1999/xlink"
        >
         [... parts of SVG left out]
        </svg>
      </button>
    `;
  }

  down() {
    if (!this.pressed) {
      this.pressed = true;
      this.dispatchEvent(new Event('button-press'));
    }
  }

  up() {
    if (this.pressed) {
      this.pressed = false;
      this.dispatchEvent(new Event('button-release'));
    }
  }
}

export default PushbuttonElement;

En principe, vous pouvez importer le pushbutton-element LitElement dans votre application React de cette manière :

import { useRef, useEffect } from 'react';
import './App.css';
import './litelements/my-element';
import './litelements/pushbutton-element';

function App() {
  const redButtonRef = useRef();
  
  const clickHandler = () => {
    console.log('RED BUTTON PRESSED!');
  }

  useEffect(() => {
    let redButton = null;

    if (redButtonRef.current) {
      redButtonRef.current.addEventListener('button-press', clickHandler);
      redButton = redButtonRef.current;
    }

    return () => {
      if (redButton) {
        redButton.removeEventListener('button-press', clickHandler);
      }  
    };
  });

  return (
    <div className="App">
      <header className="App-header">
        <my-element />
        <br />
        <wokwi-pushbutton color="red" ref={redButtonRef}/>
        <br />
        <wokwi-pushbutton color="green"/>
        <br />
        <wokwi-pushbutton color="yellow"/>
      </header>
    </div>
  );
}

export default App;

Vous pouvez voir que l’élément wokwi-pushbutton est écrit en cas kebab, au lieu de cas Pascal habituelle des éléments React. Vous pouvez transmettre les valeurs des propriétés comme d’habitude.

Le wokwi-pushbutton émet un événement lorsque le bouton est enfoncé. La gestion de cet événement est un peu différente de la gestion habituelle de l’événement React.

Gestion des événements

Pour gérer le button-press, j’utilise une référence de React pour obtenir l’élément et ajouter un auditeur d’événement. Comme j’utilise un élément de la fonction React, tout se trouve dans la fonction useEffect. Le gestionnaire d’événements envoie simplement un message à la console lorsque l’événement est déclenché.

Notez que le gestionnaire d’événements doit également se désenregistrer avec la fonction removeEventListener.

Conclusion

Dans cet exemple d’application, vous pouvez voir qu’il est possible d’intégrer les LitElements dans votre application React. Pour le traitement des événements, vous devez faire preuve d’une attention particulière, mais c’est tout à fait faisable.

Références

Application finale: https://github.com/tderflinger/react-litelement-example

LitElement: https://lit-element.polymer-project.org/

Create React App: https://create-react-app.dev/

Wokwi LitELement article de boutons : https://www.smashingmagazine.com/2020/01/recreating-arduino-pushbutton-svg/

Wokwi LitElements: https://github.com/wokwi/wokwi-elements

Web Components specs: https://www.webcomponents.org/specs

Vaadin Web Components dans React: https://vaadin.com/learn/tutorials/using-web-components-in-react

Publié le 29 décembre 2020

Thomas Derflinger

Thomas Derflinger

Je suis entrepreneur indépendant et développeur de logiciels.

Web est un sujet que j'aime beaucoup. Prenons contact!