ReactJS - Portалы: Врата в новые dimensionы ваших React приложений

Здравствуйте,野心勃勃ые разработчики React! Сегодня мы отправимся в увлекательное путешествие в мир React Portals. Представьте, что вы строите дом (ваше React приложение), и вдруг понимаете, что вам needed的秘密ный passage, чтобы transportить что-то из одной комнаты в другую, не passes через главный коридор. Именно то, что делают React Portals для ваших компонентов!

ReactJS - Portals

Что такое React Portals?

React Portals предоставляют первый класс способов рендеринга descendents в DOM узел, который существует вне DOM иерархии родительского компонента. На более простом языке, это как создание червоточины, которая позволяет вам рендерить компонент в другом месте DOM дерева, даже если он по-прежнему часть вашей React компонентной иерархии.

Зачем нам нужны Portals?

Вы можете задаться вопросом: "Почему я не могу просто рендерить мой компонент wherever хочу?" Ну, в большинстве случаев, вы можете! Но есть сценарии, где Portals могут быть полезны:

  1. Модальные对话框и
  2. Подсказки
  3. Плавающие меню
  4. Вidgets, которые нужно вывести за пределы их контейнера

Давайте погрузимся глубже в то, как работают Portals и как их использовать.

Создание вашего первого Portala

Чтобы создать Portal, мы используем метод ReactDOM.createPortal(). Вот базовый пример:

import React from 'react';
import ReactDOM from 'react-dom';

function MyPortalComponent() {
return ReactDOM.createPortal(
<h1>Я рендерюсь в другом месте!</h1>,
document.getElementById('portal-root')
);
}

В этом примере мы создаем Portal, который рендерит <h1> элемент в DOM узле с идентификатором 'portal-root'. Этот узел должен существовать где-то в вашем HTML, вне корневого элемента вашей main React приложения.

Давайте разберем метод ReactDOM.createPortal():

  1. Первый аргумент - это React элемент, который вы хотите рендерить.
  2. Второй аргумент - это DOM элемент, где вы хотите его рендерить.

Реальный пример: Модальный диалог

Давайте создадим более практичный пример - модальный对话框, который appears поверх содержимого вашего приложения.

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Modal({ isOpen, onClose, children }) {
if (!isOpen) return null;

return ReactDOM.createPortal(
<div className="modal-overlay">
<div className="modal-content">
{children}
<button onClick={onClose}>Закрыть</button>
</div>
</div>,
document.getElementById('modal-root')
);
}

function App() {
const [isModalOpen, setIsModalOpen] = useState(false);

return (
<div>
<h1>Добро пожаловать в мое приложение</h1>
<button onClick={() => setIsModalOpen(true)}>Открыть модальный диалог</button>
<Modal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h2>Это модальный диалог</h2>
<p>Он рендерится خارج главного React дерева!</p>
</Modal>
</div>
);
}

В этом примере мы создали перерабатываемый Modal компонент, который использует Portal для рендеринга своего содержимого. Компонент App контролирует видимость модального диалога с помощью хука React useState.

Давайте разберем, что происходит:

  1. Компонент Modal проверяет, должен ли он быть open (isOpen проп).
  2. Если открыт, он создает Portal, который рендерит свое содержимое в элемент 'modal-root'.
  3. Содержимое модального диалога включает кнопку закрытия, которая активирует onClose проп.
  4. В компоненте App мы используем состояние для управления видимостью модального диалога.

Пропagation событий через Portals

Один из fascininating аспектов Portals заключается в том, что несмотря на то, что они могут рендерить содержимое в anywhere в DOM дереве, событя продолжают пузыриться вверх через React дерево, как expected. Давайте посмотрим пример:

import React, { useState } from 'react';
import ReactDOM from 'react-dom';

function Parent() {
const [clicks, setClicks] = useState(0);

const handleClick = () => {
setClicks(clicks + 1);
};

return (
<div onClick={handleClick}>
<h1>Кликов: {clicks}</h1>
<Portal>
<Child />
</Portal>
</div>
);
}

function Portal({ children }) {
return ReactDOM.createPortal(
children,
document.getElementById('portal-root')
);
}

function Child() {
return <button>Нажми меня!</button>;
}

В этом примере, нажатие на кнопку внутри Portala все равно активирует обработчик кликов в родительском компоненте, увеличивая счетчик кликов. Это поведение incredibly полезно, так как оно поддерживает ожидаемое распространение событий, несмотря на то, где компонент действительно рендерится в DOM.

Лучшие практики и соображения

Используя Portals, имейте в виду следующие моменты:

  1. Доступность: Убедитесь, что содержимое вашего Portala доступно, особенно для экранных readers.
  2. Обработка событий: Помните, событья пузырятся через React дерево, а не DOM дерево.
  3. Оформление: Содержимое Portala может require отдельных соображений по оформлению.
  4. Очистка: Не забудьте очистить ваши Portals, когда компонент отмонтируется.

Методы Portals

Вот таблица ключевых методов, связанных с React Portals:

Метод Описание
ReactDOM.createPortal(child, container) Создает portal. child - любой рендеримый React child, а container - DOM элемент.
ReactDOM.unmountComponentAtNode(container) Удаляет смонтированный React компонент из DOM и очищает его обработчики собыний и состояние.

Заключение

React Portals - это мощная функция, которая позволяет вам вырваться из традиционной иерархии компонентов при рендеринге. Они особенно полезны для создания модальных диалогов, подсказок и других UI элементов, которые должны визуально "вырываться" из своих контейнеров.

помните, с великой силой приходит великая ответственность! Используйте Portals мудро и всегда учитывайте влияние на структуру и доступность вашего приложения.

Счастливого кодирования, и пусть ваши Portals всегда ведут в захватывающие новые dimensionы ваших React приложений!

Credits: Image by storyset