PassFront
  1. PassFront
  2. База знаний
  3. Компоненты

Приведи пример использования React Portal.

Компоненты

Классический пример портала — модальное окно, которое должно отрисоваться поверх всего, независимо от CSS-контекста родителей.

Пример: модалка

import { createPortal } from 'react-dom';

const Modal = ({ open, onClose, children }) => {
  if (!open) return null;

  return createPortal(
    <div className="overlay" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        {children}
        <button onClick={onClose}>Закрыть</button>
      </div>
    </div>,
    document.body, // рендер вне иерархии родителя
  );
};

Использование:

const ProductCard = ({ product }) => {
  const [open, setOpen] = useState(false);

  return (
    <div className="card"> {/* у карточки overflow: hidden */}
      <button onClick={() => setOpen(true)}>Подробнее</button>
      <Modal open={open} onClose={() => setOpen(false)}>
        <ProductDetails product={product} />
      </Modal>
    </div>
  );
};

Что демонстрирует пример

  • Без портала модалка обрезалась бы overflow: hidden карточки и проигрывала бы соседям по z-index. С порталом её DOM — прямой ребёнок body.
  • В React-дереве Modal остаётся внутри ProductCard: видит контекст (тему, стор), а клики из модалки всплывают в React-родителей, поэтому работает stopPropagation.
  • Состояние open живёт у владельца — портал не меняет поток данных.

Другие типичные применения

  • Тултипы и поповеры (позиционирование относительно viewport).
  • Тосты/уведомления в углу экрана (отдельный <div id="toasts">).
  • Дропдауны внутри скроллируемых контейнеров с overflow.

Коротко для собеседования

Типовой пример — модалка через createPortal(jsx, document.body): DOM рендерится вне родителя (не режется overflow/z-index), но в React-дереве компонент остаётся на месте — контекст доступен, события всплывают. Так же делаются тултипы, тосты и дропдауны.

Другие вопросы раздела