Portail React.js

La magie du rendu des éléments en dehors du propre arbre DOM

Téléportation dans React.js

Saviez-vous que React fournit un composant spécial et très puissant appelé « Portail » qui peut monter ses enfants à un endroit complètement différent dans votre application ? Sinon, il est temps d'apprendre quelque chose de nouveau !

L'anatomie d'un portail React.js

Voici un aperçu rapide du fonctionnement du composant Portal dans React.js auparavant.

  • Quelque part dans votre code, vous montez un élément qui hébergera les enfants du portail
  • Ensuite, vous obtenez une référence à cet élément
  • Quelque part ailleurs dans votre application, vous montez ensuite le composant Portal et transmettez la référence obtenue à partir de l'élément hôte
  • Tout ce qui est maintenant monté à l'intérieur du portail sera en fait monté dans l'hôte dès la première étape

Pour mieux comprendre ce qui se passe, j'ai créé les visualisations simples suivantes pour illustrer la fonctionnalité du portail.

Image ee9c2dac28e7

Image 70ff8978589d

Image 886ed0a34985

S'appuyant sur ces images, les graphiques suivants montrent le même processus, mais cette fois avec des exemples de code simplifiés.

Image dd655b015a22

Image ab94e9940e3a

Le portail est encore plus puissant que vous ne le pensez au départ. Il permet même de rendre plusieurs enfants de plusieurs portails dans le même élément cible. L'ordre de montage des Portails définit également l'ordre des éléments dans l'hôte.

Image de39ae9a02a2

Image b12fdf680f24

Partager la référence à l'élément hôte qui contiendra tous les enfants téléportés est également très facile. La documentation officielle décrit l'utilisation de document.getElementById, mais vous pouvez également utiliser le crochet useRef-hook de React.js. L'exemple de code suivant illustre une implémentation simple qui montre tout ce qui a été décrit jusqu'à présent.

import React, { useEffect, useRef, useState } from "react";
import ReactDOM, { createPortal } from "react-dom";

//
// Link to sandbox:
// 👉 https://codesandbox.io/s/react-16-8-0-forked-d8lm1?file=/src/index.js:0-1067
//

// A simple demonstration of the React-Portal
// w/ multiple portals for the same target.
function App() {
  const ref = useRef(null);
  const [isRefReady, setIsRefReady] = useState(false);

  // Run one more render to actually
  // show the content of our portal.
  // This is necessary, as the setter
  // for the 'ref' alone won't trigger
  // a render.
  useEffect(() => {
    setIsRefReady(Boolean(ref));
  }, []);

  return (
    <div>
      <div>
        {/* The 'target' aka host for our portals. */}
        <header ref={ref} style={{display: "flex", gap: 8 }} />
        <hr/>
      </div>
      <h1>
        Debug
      </h1>
      {isRefReady && createPortal(<button>one</button>, ref.current)}
      {isRefReady && createPortal(<button>two</button>, ref.current)}
      <div>
        {isRefReady && createPortal(<button>three</button>, ref.current)}
      </div>
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector("#root"));

Comment le composant Portal permet un codage plus simple

Le cas d'utilisation le plus courant du portail React.js est probablement l'implémentation d'un composant modal. Vous pouvez simplement définir la cible à la racine de l'arborescence de votre application et utiliser le composant Portal pour monter un modal de partout, flottant de manière fiable au-dessus de tout contenu.

Un autre cas d'utilisation que j'ai implémenté est l'utilisation d'un conteneur d'onglets. Comme un conteneur d'onglets nécessite à la fois un élément d'onglet lui-même ainsi que le contenu à afficher lorsque l'onglet est sélectionné, je définis simplement deux hôtes, un pour la ligne d'onglets et l'autre pour le contenu sélectionné.

Ensuite, je monte simplement un tableau de composants qui utilisent chacun un portail pour l'onglet ainsi que le contenu sélectionné. Cela me permet de placer la logique métier là où elle appartient réellement - dans chaque composant séparé.

Image 2761da74cf8c

Image e7810bb469d2

Il existe certainement des cas d'utilisation encore plus intéressants pour le composant Portal. Je pense que le plus grand avantage que cela permet est le couplage étroit de la logique métier dans un seul composant, dont les enfants sont ensuite montés à différents endroits. Ce modèle permet une grande flexibilité et une grande personnalisation, mais peut entraîner une confusion dans votre base de code sur la manière dont les vues sont réellement liées.

Veuillez également consulter la documentation officielle pour tous les détails concernant les portails React.js.