В контексте библиотеки MUI (Material-UI) портал — это механизм, позволяющий рендерить React-компоненты вне текущей иерархии DOM, сохраняя при этом реактивность и контекст приложения. Это особенно важно для компонентов, которые должны визуально “выходить” за пределы родительского контейнера, например, модальные окна, всплывающие подсказки (Tooltips), меню и Snackbar.
Основная идея порталов заключается в том, что они создают отдельный узел DOM, куда React будет монтировать содержимое компонента, но при этом сохраняется связь с React-контекстом родителя, включая темы, состояние и контекст MUI.
В MUI для работы с порталами используется компонент
Portal из пакета
@mui/material. Его базовое использование выглядит так:
import React from 'react';
import { Portal, Button, Paper } from '@mui/material';
export default function SimplePortal() {
const [open, setOpen] = React.useState(false);
return (
<div>
<Button variant="contained" onCl ick={() => setOpen(!open)}>
Toggle Portal
</Button>
{open && (
<Portal>
<Paper
elevation={4}
style={{
position: 'absolute',
top: '50px',
left: '50px',
padding: '16px',
}}
>
Содержимое портала
</Paper>
</Portal>
)}
</div>
);
}
Ключевые моменты:
Portal автоматически рендерит содержимое в корне DOM
(document.body) по умолчанию.position: absolute/fixed), так как он не ограничен
размерами родителя.Иногда требуется рендерить портал не в
body, а в специфический контейнер. Для этого
используется проп container:
import React, { useRef, useState } from 'react';
import { Portal, Paper, Button } from '@mui/material';
export default function ContainerPortal() {
const [open, setOpen] = useState(false);
const containerRef = useRef(null);
return (
<div ref={containerRef} style={{ position: 'relative', height: '200px' }}>
<Button onCl ick={() => setOpen(!open)}>Toggle Portal</Button>
{open && (
<Portal container={containerRef.current}>
<Paper
elevation={3}
style={{
position: 'absolute',
top: '10px',
left: '10px',
padding: '8px',
}}
>
Портал в пользовательском контейнере
</Paper>
</Portal>
)}
</div>
);
}
Особенности:
ref.Модальные окна (Dialog) MUI
использует портал для корректного отображения модального контента поверх
всех элементов страницы. Это гарантирует, что модальное окно не
будет ограничено стилями родителя.
Всплывающие подсказки (Tooltip) и меню
(Menu) Portals позволяют этим компонентам
выходить за пределы родительского контейнера, избегая
обрезки через overflow: hidden.
Snackbar и уведомления Сообщения могут отображаться над основным контентом, не влияя на текущую структуру страницы.
Поскольку портал рендерится вне иерархии родителя, CSS-позиционирование играет ключевую роль:
position: absolute — позиционирует относительно
ближайшего родителя с position: relative.position: fixed — позиционирует относительно окна
браузера, игнорируя прокрутку родителя.z-index необходимо для корректного
отображения поверх других элементов.<Portal>
<Paper
style={{
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: 1300, // MUI рекомендует использовать системные значения z-index
padding: '12px',
}}
>
Уведомление
</Paper>
</Portal>
Содержимое портала автоматически наследует тему MUI,
что особенно важно для компонентов, использующих стили через
useTheme или styled. Даже находясь вне
DOM-иерархии родителя, портал сохраняет все провайдеры
контекста, включая ThemeProvider,
CssBaseline и LocalizationProvider.
import { ThemeProvider, createTheme, Portal, Paper } from '@mui/material';
const darkTheme = createTheme({ palette: { mode: 'dark' } });
function ThemedPortalExample() {
return (
<ThemeProvider theme={darkTheme}>
<Portal>
<Paper elevation={3} style={{ padding: '16px' }}>
Темная тема применяется внутри портала
</Paper>
</Portal>
</ThemeProvider>
);
}
Fade или
Grow вместе с Portal.container
проп для привязки портала к конкретной области, чтобы избежать
неожиданных проблем с позиционированием и overflow.MUI Portal обеспечивает гибкий инструмент для рендеринга компонентов вне стандартной иерархии DOM, сочетая преимущества контекста React с возможностью абсолютного позиционирования. Это позволяет строить сложные интерфейсы с модальными окнами, всплывающими меню и уведомлениями, не ограничивая их визуально структурой родительских элементов.