Согласно официальной документации по React, порталы представляют собой первоклассный способ отображения дочерних компонентов в узел DOM вне DOM-иерархии родительского компонента, определяемой иерархией дерева компонентов. Порталы применяют в ситуациях, когда необходимо, чтобы дочерние компоненты визуально вырывались из родительского контейнера. Типичные примеры использования порталов:
- Модальные диалоговые окна.
- Всплывающие подсказки.
- Всплывающие визитки.
- Загрузчики.
Портал создаётся с помощью ReactDOM.createPortal(child, container)
. Здесь child
— это элемент, фрагмент или строка React, а container
— это местоположение или узел DOM, в который должен добавляться портал.
Вот пример компонента modal
, созданного с использованием приведённого выше API:
const Modal =({ message, isOpen, onClose, children })=> {
if (!isOpen) return null
return ReactDOM.createPortal(
<div className="modal">
<span className="message">{message}</span>
<button onClick={onClose}>Close</button>
</div>,
domNode)
}
Несмотря на то, что портал отображается вне родительского элемента DOM, ведёт он себя аналогично обычному компоненту React внутри приложения. Он может получить доступ к props
и context
API. Почему? Потому что портал находится внутри иерархии дерева React.
С реальным примером порталов в React можно ознакомиться в этом компоненте, выложенном в разделе компонентов на сайте Bit (вы тоже можете задействовать этот сайт для выкладывания там компонентов и повторного их использования):
Для чего нужны порталы
При использовании modal
внутри конкретного элемента (родительского компонента) высота и ширина этого modal
будут унаследованы от компонента, в котором находится modal
. Поэтому есть вероятность того, что modal
будет «обрезан», вследствие чего он будет неправильно отображаться в приложении. Во избежание этой проблемы традиционному modal
потребуются такие свойства стиля CSS, как overflow:hidden
и z-index
.
В результате приведённого выше примера кода, modal
будет отображён в root
внутри вложенных компонентов. При просмотре кода приложения в браузере с помощью функции inspect
элементы будут показаны следующим образом:
Посмотрим, как нам здесь задействовать портал React. Следующий код решает этот вопрос через createPortal()
для создания DOM-узла вне иерархии root
:
const Modal =({ message, isOpen, onClose, children })=> {
if (!isOpen) return null;
return ReactDOM.createPortal(
<div className="modal">
<span>{message}</span>
<button onClick={onClose}>Close</button>
</div>
,document.body);
}function Component() {
const [open, setOpen] = useState(false)
return (
<div className="component">
<button onClick={() => setOpen(true)}>Open Modal</button>
<Modal
message="Hello World!"
isOpen={open}
onClose={() => setOpen(false)}
/>
</div>
)
}
Ниже показана иерархия дерева DOM, которая будет получена при использовании порталов React. В ней modal
будет добавлен вне root
, находясь с ним на одном уровне:
Размеры компонента modal
не будут унаследованы или изменены родительскими компонентами, потому что он отображается вне корневой иерархии root
.
Этот пример можно найти в CodeSandbox и поэкспериментировать с кодом, чтобы воочию убедиться в том, как работают порталы, и проработать рассмотренные нами вопросы.
Что надо учитывать при использовании порталов
Имея дело с порталами в React, надо помнить о нескольких вещах. Эти поведения не сразу заметишь, если они тебе не знакомы. Поэтому немного расскажем и о них тоже.
- Всплывающее событие будет работать, как обычно, распространяя события на предков в дереве React, независимо от местоположения узла портала в DOM.
- React контролирует узлы портала и его жизненный цикл при отображении дочерних элементов с помощью этих порталов.
- Порталы влияют только на структуру DOM для HTML и не затрагивают дерево компонентов React.
- Предварительно определяется точка монтирования HTML: при использовании порталов необходимо определить HTML-элемент DOM в качестве точки монтирования компонента портала.
Заключение
Порталы в React могут пригодиться, когда необходимо отобразить дочерние компоненты вне обычной иерархии DOM. При этом используется иерархия дерева компонентов React и не нарушается поведение по умолчанию, определённое для распространения событий. Таким образом отображаются такие компоненты, как modal
, всплывающие подсказки или сообщения и многие другие.
Более подробная информация о порталах содержится в официальной документации React.
Спасибо за внимание!
Читайте также:
- Перехват ошибок в компоненте React
- Как скоро хуки вытеснят классы React?
- Первые шаги в анимации React Native
Читайте нас в Telegram, VK и Дзен
Перевод статьи Madushika Perera: Understanding React Portals and Its Use-Cases