React — это популярная библиотека JavaScript для создания пользовательских интерфейсов. Одной из мощных функций React является использование порталов, которые позволяют разработчикам отображать контент за пределами обычной древовидной структуры React. В этой статье вы узнаете все о том, что такое порталы, как их использовать, а также о некоторых распространенных случаях использования порталов в приложениях React.
Что такое порталы?
Порталы React предоставляют способ рендеринга контента за пределами обычной иерархии DOM компонента. Это означает, что вы можете визуализировать дочерний компонент в другом месте дерева DOM, чем его родительский компонент.
С технической точки зрения, порталы в React работают, создавая новый узел DOM и отображая в нем компонент. Этот новый узел добавляется к элементу body документа HTML, который находится за пределами обычного дерева компонентов React. Визуализированное содержимое может быть расположено и оформлено независимо от родительского компонента.
Преимущества использования порталов
Использование порталов в React имеет несколько преимуществ:
- Гибкость. Порталы позволяют отображать компонент за пределами его родительского контейнера, что может быть полезно в ситуациях, когда вам нужно отобразить содержимое в другой части страницы.
- Улучшенная производительность. Отрисовывая компонент вне его родительского контейнера, вы можете уменьшить количество манипуляций с DOM, необходимых для обновления компонента, что может повысить производительность.
Распространенные варианты использования порталов
Порталы можно использовать для различных элементов пользовательского интерфейса. Вот несколько распространенных вариантов использования порталов в React:
- Модальные
- Диалоговые окна
- Подсказки
- Подсказки при наведении
- Поповеры
- Выпадающие меню
- Погрузчики
Как создать портал в React
Чтобы создать портал в React, мы используем createPortal()
API. Этот метод принимает два аргумента:
children
: любой допустимый элемент React, который можно отобразить.domNode
: DOM-контейнер, в котором должен отображатьсяchildren
.
Вот синтаксис:
createPortal(children, domNode);
Пример:
import { createPortal } from "react-dom"; const Modal = () => { return ( <div className="modal"> <h1>Modal Content</h1> </div> ); }; const Portal = () => { return createPortal(<Modal />, document.getElementById("modal-root")); };
В приведенном выше примере мы определяем модальный компонент, который хотим визуализировать с помощью портала. Затем мы определяем компонент портала, который использует метод createPortal()
для рендеринга модального компонента в контейнере с идентификатором modal-root
.
Как использовать порталы
Чтобы увидеть, как работают порталы, давайте создадим простое приложение React, которое использует порталы для рендеринга модального компонента. Если вы работаете над существующим проектом, вы можете пропустить первый шаг. Полный код этого примера доступен на GitHub.
Шаг 1. Инициализируйте приложение React
Сначала создайте новое приложение React с помощью Vite:
npm create vite@latest my-react-app --template react
Перейдите в каталог проекта и установите зависимости:
cd my-react-app npm install npm run dev
Шаг 2: Создайте контейнер портала
Затем создайте элемент контейнера в файле index.html
, в котором будет размещаться портал. Этот элемент должен быть расположен за пределами корневого узла приложения React, который обычно представляет собой div с идентификатором root
.
В этом примере мы создадим div с идентификатором portal
и добавим его в тело HTML-файла:
<body> <div id="root"></div> <div id="portal"></div> </body>
Шаг 3: Создайте компонент Overlay
Мы будем использовать компонент Overlay в качестве эффекта фона при открытии модального окна, а также создадим внутри него портал.
Создайте новый файл Overlay.jsx
в каталоге src
и вставьте следующий код:
import React from "react"; import { createPortal } from "react-dom"; import "./App.css"; const Overlay = ({ closeModal, children }) => { return createPortal( <div className="overlay" onClick={closeModal}> {children} </div>, document.getElementById("portal") ); }; export default Overlay;
Компонент Overlay возвращает фрагмент JSX, который использует метод createPortal()
из пакета react-dom
для рендеринга div с дочерними элементами внутри портала.
Затем мы устанавливаем событие onClick
для div, чтобы вызвать функцию closeModal
, которая передается как свойство.
Шаг 4: Создайте модальный компонент
Затем создайте новый файл Modal.jsx
в каталоге src
и добавьте следующий код.
import React from "react"; import Overlay from "./Overlay"; import "./App.css"; const Modal = ({ closeModal }) => { return ( <Overlay closeModal={closeModal}> <div className="modal" onClick={(e) => e.stopPropagation()}> <h3>Modal</h3> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Odit, libero. Exercitationem quod quam perspiciatis quasi voluptate sint facilis quia praesentium pariatur veniam quidem nam, ullam porro eveniet molestiae minima eligendi. </p> <button onClick={closeModal}>Close</button> </div> </Overlay> ); }; export default Modal;
В приведенном выше коде событие onClick
для div настроено на остановку распространения события, чтобы щелчок внутри модального окна не закрывал его.
Кроме того, событие onClick
для элемента кнопки вызовет функцию closeModal
, которая была передана в качестве реквизита.
Шаг 5. Отредактируйте компонент приложения
Скопируйте и вставьте следующий код в файл App.jsx
.
import { useState } from "react"; import Modal from "./Modal"; import "./App.css"; function App() { // State to manage whether the modal is open or closed const [modalOpen, setModalOpen] = useState(false); // Function to toggle the state between open and closed const handleModal = () => { setModalOpen(!modalOpen); }; return ( <div className="App"> <h1>React Modal Demo</h1> <p> This is a demo of how to use portals to create a modal component in React. </p> <button onClick={handleModal}>Open Modal</button> {modalOpen && <Modal closeModal={() => setModalOpen(false)} />} </div> ); } export default App;
Здесь мы определяем состояние для управления тем, открыто ли модальное окно или закрыто, и функцию для переключения состояния. При нажатии кнопки «Открыть модальный» вызывается функция handleModal
, и состояние modalOpen
соответственно обновляется.
Если состояние равно true
, визуализируется модальный компонент, который включает кнопку «Закрыть», которая устанавливает для состояния modalOpen значение false.
Шаг 6: Стиль приложения
Наконец, давайте стилизуем приложение. Добавьте следующий код в файл App.css
:
Вот как выглядит финальное приложение:
Теперь давайте подробнее рассмотрим, как это работает. Откройте Инструменты разработчика в браузере и проверьте страницу. Вы заметите, что пока модальное окно закрыто, div portal
пуст.
Когда вы нажимаете кнопку, чтобы открыть модальное окно, оно отображается внутри div portal
, как мы и указали.
Новые узлы DOM теперь монтируются внутри узла portal
вместо узла App
, указанного в исходном коде. Это демонстрирует функциональность порталов в действии.
Всплытие событий и порталы
Всплывание событий относится к тому, как события распространяются от дочерних компонентов к родительским компонентам в дереве компонентов. В случае порталов React это означает, что даже если мы визуализируем портал вне родительского элемента DOM, он по-прежнему ведет себя как стандартный компонент React с доступом к свойствам и состоянию, поскольку он остается в иерархии дерева DOM.
Поскольку порталы влияют только на структуру HTML DOM, а не на дерево компонентов React, такие функции, как Context API и пузырьковое воспроизведение событий, продолжают работать, как и раньше.
Чтобы предотвратить всплытие событий, как показано в примере, вы можете использовать метод stopPropagation()
, чтобы убедиться, что срабатывает только прослушиватель событий в контейнере портала.
Подведение итогов
Порталы в React — это мощная функция, которая позволяет разработчикам отображать контент за пределами обычной иерархии компонентов. Это может быть полезно для создания модальных окон, всплывающих окон и других элементов пользовательского интерфейса, которые необходимо позиционировать относительно определенного элемента или отображать поверх основного интерфейса приложения.
При использовании порталов важно помнить о некоторых передовых методах.
- Во-первых, всегда очищайте узел портала при размонтировании компонента. Это можно сделать с помощью хука
useEffect
и методаremoveChild
. - Во-вторых, будьте осторожны, чтобы не использовать порталы чрезмерно, так как они могут усложнить ваш код.
- Наконец, всегда тщательно проверяйте свои порталы на наличие проблем с доступностью, поскольку иногда они могут вызывать неожиданное поведение в определенных браузерах или программах чтения с экрана. Обязательно следуйте Практикам создания модальных окон WAI-ARIA при работе с модальными окнами.
Спасибо за чтение! Я надеюсь, что вы нашли эту статью полезной. Если да, то ставьте лайк и делитесь с друзьями и коллегами :)
Я хотел бы связаться с вами на Twitter | ЛинкедИн | Гитхаб | "Портфолио".
Удачного кодирования!
Ресурсы
- Реагировать на официальные документы
- Упрощенная веб-разработка: изучите портал React за 12 минут, создав модальное окно
- Всплывание и захват событий в React
Первоначально опубликовано на https://israelmitolu.hashnode.dev.