Что такое порталы в React и когда они нужны?
В версии React 16.0 появились порталы React. Порталы в React - это способ рендеринга дочерних компонентов в DOM-узел, который обычно находится вне иерархии DOM родительского компонента.
До появления порталов React было очень сложно вывести дочерний компонент за пределы иерархии его родительского компонента. Каждый компонент React в приложении React попадает под корневой элемент.
Но концепция React-порталов дает нам возможность вырваться из этого дерева dom и отобразить компонент на узел dom, который не находится под этим корневым элементом. Это нарушает традицию, согласно которой компонент должен быть отображен как новый элемент и следовать иерархии «родитель-ребенок». Порталы обычно используются в модальных диалоговых окнах, картах наведения, загрузчиках и всплывающих сообщениях. Ниже приведен синтаксис порталов React.
Синтаксис
import ReactDOM from "react-dom";
// createPortal is a function of ReactDom, always import ReactDom
// before using their property.
ReactDOM.createPortal(child, container)
Параметры:
child
: Это может быть элемент React, строка или фрагмент.container
: Это узел DOM.
В приведенном выше синтаксисе у нас есть два параметра: первый - дочерний элемент, который может быть элементом React, строкой или фрагментом, а второй - контейнер, который представляет собой узел (или местоположение) DOM, лежащий вне иерархии DOM родительского компонента, в который будет вставлен наш портал.
Преимущества порталов React
- Event Bubbling внутри портала: Хотя мы не рендерим портал внутри родительского DOM-элемента, его поведение все равно похоже на поведение обычного React-компонента внутри приложения. Он может получить доступ к реквизитам и состоянию, поскольку находится в иерархии дерева DOM.
- React-порталы могут использовать Context API для передачи данных в компоненты.
index.html
<!-- Filename - public/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon"
href="%PUBLIC_URL%/favicon.ico" />
<title>React App</title>
</head>
<body
style="text-align: center; margin: auto;">
<div id="root"></div>
<div id="portal"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty
page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body>
tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn
build`.
-->
</body>
</html>
App.js
// Filname - App.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
class Portal extends Component {
render() {
// Creating portal
return ReactDOM.createPortal(
<button>Click</button>,
document.getElementById("portal")
);
}
}
class App extends Component {
constructor(props) {
super(props);
// Set initial state
this.state = { click: "" };
// Binding this keyword
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// This will trigger when the button
// inside Portal is clicked, It updates
// Parent's state, even though it is not
// rendered inside the parent DOM element
if (this.state.click == "")
this.setState((prevState) => ({
click: "Welcome to Portal demo",
}));
else {
this.setState({ click: "" });
}
}
render() {
return (
<div onClick={this.handleClick}>
<h1 style={{ color: "green" }}>
component which have id
"root"
</h1>
<h2 style={{ color: "Green" }}>
{this.state.click}
</h2>
<Portal />
</div>
);
}
}
export default App;
Когда нужны порталы React?
В основном порталы нужны, когда родительский компонент React имеет скрытое значение свойства overflow (overflow: hidden)
или стиля z-index, а нам нужно, чтобы дочерний компонент открыто выходил из текущей иерархии дерева.
Ниже приведены примеры, когда нам нужны порталы React:
- Диалоги
- Модули
- Всплывающие подсказки
- Рекламные карточки
Во всех этих случаях мы отображаем элементы за пределами родительских компонентов в дереве DOM.