Portale React.js

La magia di rendere gli elementi al di fuori del proprio albero DOM

Teletrasporto in React.js

Sapevi che React fornisce un componente speciale e molto potente chiamato "Portal" che può montare i suoi figli in un posto completamente diverso all'interno della tua app? In caso contrario, è tempo di imparare qualcosa di nuovo!

L'anatomia di un portale React.js

Ecco una rapida panoramica di come funziona il componente Portal in React.js prima.

  • Da qualche parte nel tuo codice, monti un elemento che ospiterà i figli del Portale
  • Quindi ottieni un riferimento a questo elemento
  • Da qualche altra parte nella tua app, monti il componente Portal e passi il riferimento ottenuto dall'elemento host
  • Tutto ciò che è ora montato all'interno del portale verrà effettivamente montato nell'host dal primo passaggio

Per capire meglio cosa sta succedendo, ho creato le seguenti semplici visualizzazioni per illustrare la funzionalità del portale.

Image ee9c2dac28e7

Image 70ff8978589d

Image 886ed0a34985

Basandosi su queste immagini, i grafici seguenti mostrano lo stesso processo, ma questa volta con esempi di codice semplificati.

Image dd655b015a22

Image ab94e9940e3a

Il Portale è ancora più potente di quanto potresti pensare inizialmente. Consente anche di eseguire il rendering di più bambini da più portali nello stesso elemento di destinazione. L'ordine di montaggio dei Portal definisce anche l'ordine degli elementi nell'host.

Image de39ae9a02a2

Image b12fdf680f24

Anche condividere il riferimento all'elemento host che conterrà tutti i bambini teletrasportati è molto semplice. La documentazione ufficiale descrive l'uso di document.getElementById, ma puoi anche usare useRef-hook di React.js. L'esempio di codice seguente mostra una semplice implementazione che mostra tutto ciò che è stato descritto fino ad ora.

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"));

In che modo il componente Portal consente una codifica più semplice

Probabilmente il caso d'uso più comune per il portale React.js è l'implementazione di un componente Modal. Puoi semplicemente definire il target alla radice dell'albero della tua app e utilizzare il componente Portal per montare una modale da qualsiasi luogo, fluttuando in modo affidabile sopra tutti i contenuti.

Un altro caso d'uso che ho effettivamente implementato è l'uso di un contenitore di schede. Poiché un contenitore di schede richiede sia un elemento della scheda stesso sia il contenuto di cui eseguire il rendering quando la scheda è selezionata, definisco semplicemente due host, uno per la riga della scheda e l'altro per il contenuto selezionato.

Quindi monto semplicemente una serie di componenti che utilizzano ciascuno un portale per l'elemento della scheda e il contenuto selezionato. Questo mi permette di posizionare la logica aziendale dove effettivamente appartiene - in ogni componente separato.

Image 2761da74cf8c

Image e7810bb469d2

Ci sono certamente casi d'uso ancora più interessanti per il componente Portal. Il più grande vantaggio che penso consenta è lo stretto accoppiamento della logica di business in un unico componente, i cui figli vengono poi montati in luoghi diversi. Questo modello consente una grande flessibilità e personalizzazione, ma può portare a confusione nella tua base di codice su come le visualizzazioni siano effettivamente correlate.

Dai anche un'occhiata alla documentazione ufficiale per tutti i dettagli sui portali React.js.