React 16, выпущенный в сентябре 2017 года, представил порталы.
Портал – это способ визуализации элемента за пределами его иерархии компонентов, в отдельном компоненте.
Когда это событие визуализируется, события, происходящие на нем, управляются иерархией компонентов React, а не иерархией, заданной позицией DOM элемента.
Отсюда и название “портал”: элемент находится где-то в дереве DOM, которое находится за пределами обычного дерева компонентов React, но дерево компонентов React, включающее его, все еще отвечает.
React предлагает простой API для этого, ReactDOM.создать портал()
, который принимает 2 аргумента. Первый – это элемент для визуализации, второй – элемент DOM, где его нужно визуализировать.
Классическим вариантом использования для этого являются модальные окна.
Модель для рендеринга в полноэкранном режиме должна находиться за пределами элемента, чтобы ее можно было правильно стилизовать с помощью CSS.
Так если модель определена как компонент:
class Modal extends React.Component { constructor(props) { super(props) this.el = document.createElement('div') } componentDidMount() { document.getElementById('modal').appendChild(this.el) } componentWillUnmount() { document.getElementById('modal').removeChild(this.el) } render() { return ReactDOM.createPortal( this.props.children, this.el ) } }
У нас может быть компонент приложения, отображающий его, и все события, происходящие в Модальном компоненте, будут обрабатываться приложением, даже если технически модальное отображается в другом дереве DOM:
class App extends React.Component { constructor(props) { super(props) this.state = {showModal: false} this.handleShow = this.handleShow.bind(this) this.handleHide = this.handleHide.bind(this) } handleShow() { this.setState({showModal: true}) } handleHide() { this.setState({showModal: false}) } render() { const modal = this.state.showModal ? () : '' return ( The modalThe app {modal}) } } ReactDOM.render(, document.getElementById('app'))
Смотрите полный пример на https://codepen.io/flaviocopes/pen/KbdagX
Оригинал: “https://flaviocopes.com/react-portals/”