Lorsque nous créons des composants dans React, ils existent normalement dans l'arborescence des composants. C'est généralement bien, mais parfois nous voulons que certaines parties d'un composant apparaissent en dehors de l'arborescence des composants , ou quelque part complètement différent.
Il s'agit d'une exigence courante lorsque nous créons des fenêtres contextuelles modales, qui doivent être au-dessus de tous les autres composants.
Nous pouvons les créer dans un composant, mais en fin de compte, nous les voulons avant tout, et les avoir imbriqués dans de nombreux composants peut causer des problèmes car leur z-index
tombera en dessous de tout ce qu'ils contiennent :
Pour résoudre ce problème, nous pouvons téléporter le modal hors de son propre composant et dans une autre partie de notre modèle en utilisant createPortal
.
Cela nous permet de placer notre composant n'importe où, comme à la base de l'arborescence HTML, à l'intérieur de la balise body
ou à l'intérieur d'un autre élément.
Même si l'élément existe dans l'arborescence des composants, createPortal
nous donne le pouvoir de le placer où bon nous semble.
Pour vous montrer comment fonctionnent les portails, considérez que nous avons le code React de base suivant dans notre fichier App.js
Ici, nous voulons que le modal apparaisse au-dessus de tout le reste. En tant que tel, nous avons créé une div
appelée #modal-container
. C'est finalement là que nous voulons que tous nos modaux entrent :
import logo from './logo.svg'; import './App.css'; import { useState } from 'react' import Modal from './components/Modal.js'; function App() { const [isModalOpen, setIsModalOpen] = useState(false); return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <button onClick={() => setIsModalOpen(!isModalOpen)}> Click to Open Modal </button> <Modal modalState={isModalOpen} onClickEvent={() => setIsModalOpen(!isModalOpen)}> This is Modal Content! </Modal> </header> <div id="modal-container"></div> </div> ); } export default App;
Dans App.js
, j'ai importé un composant appelé Modal
. Il s'agit de notre composant modal, qui apparaîtra chaque fois que l'utilisateur cliquera sur le bouton.
Chaque fois que isModalOpen
est défini sur true en utilisant setIsModalOpen()
, le modal doit apparaître. Sinon, il disparaîtra.
J'ai aussi un peu de CSS pour m'assurer que nos modaux apparaissent bien au-dessus de tout le reste :
#modal-container { position: absolute; top: 0; left: 0; width: 100%; z-index: 9999; height: 100%; pointer-events: none; } .modal { position: absolute; top: 200px; background: white; border-radius: 4px; left: calc(50% - 100px); width: 200px; }
Créer un portail est assez simple - il y a une fonction, createPortal()
. Au lieu de renvoyer du DOM dans React, nous renvoyons le Portal
à la place.
createPortal()
accepte deux arguments - l'élément DOM que nous voulons renvoyer - dans ce cas, le modal - et l'élément DOM vers lequel nous voulons téléporter notre élément DOM.
Donc, notre deuxième argument est document.getElementById('modal-container')
, puisque nous voulons mettre tous nos modaux dans #modal-container
:
import { createPortal } from 'react-dom'; function Modal({modalState, onClickEvent}) { if(!modalState) return null; return ( createPortal( <div className="modal"> <button onClick={onClickEvent}>Close Modal</button> <div className="modal-content">Modal Content goes here</div> </div>, document.getElementById('modal-container') ) ); }; export default Modal;
Bien que nous ayons téléporté notre élément DOM vers modal-container
, il se comporte toujours comme un enfant React normal. Étant donné que le portail existe toujours dans l'arborescence React, des fonctionnalités telles que le contexte dans lequel se trouve l'élément fonctionnent toujours de la même manière.
Il convient également de noter que bien que nous ayons modal-container
et Modal
dans le même fichier, l'endroit où vous téléportez votre élément DOM peut se trouver n'importe où dans votre code React.
Ainsi, vous pouvez le téléporter vers un sous-composant, un élément ou un parent complètement différent n'importe où dans le DOM. C'est assez puissant et utile - alors utilisez-le judicieusement.
Revenons à notre App.js
HTML :
<!-- .... --> <button onClick={() => setIsModalOpen(!isModalOpen)}> Click to Open Modal </button> <Modal modalState={isModalOpen} onClickEvent={() => setIsModalOpen(!isModalOpen)}> This is Modal Content! </Modal> </header> <div id="modal-container"></div>
Maintenant, même si Modal
se trouve dans notre en-tête, il apparaîtra dans #modal-container
chaque fois que nous ouvrirons le modal à l'aide du bouton :
Les portails sont un outil assez puissant dans React. Ils sont un moyen utile de résoudre le problème principal des systèmes à base de composants - transporter certains éléments avant tout le reste.
En tant que tel, j'espère que vous avez apprécié ce guide des portails React. Si vous apprenez React, je vous suggère de maîtriser d'abord Javascript - ce que vous pouvez faire avec mon manuel Javascript complet.
Passe une bonne journée.