30% offEnding soon
PortalLoading saved progress…

Portal

A portal renders React children into a DOM container outside their parent's physical DOM subtree while keeping them in the same React tree. Implement a Portal component that either borrows a caller-provided container or creates one host under document.body. Follow React's createPortal contract, including context continuity and React-tree event bubbling.

Signature

type PortalProps = {
  children: React.ReactNode;
  container?: Element | DocumentFragment | null;
};

function Portal({ children, container = null }: PortalProps): React.ReactPortal | null;

Examples

<Portal>
  <div>Notifications</div>
</Portal>

// After the component mounts, one marked host is appended to document.body.
// The div renders inside that host. Unmounting removes the owned host.
const sidebar = document.querySelector('#sidebar');

<Portal container={sidebar}>
  <AccountMenu />
</Portal>

// AccountMenu renders inside #sidebar. The Portal never removes #sidebar.

Notes

  • Wait for the effect — return null on the first render. If document is unavailable, keep rendering null.
  • Own one default host — create exactly one div, set data-uiready-portal="", append it to document.body, and reuse it across ordinary rerenders.
  • Respect ownership — remove only a host your component created. Never append or remove the caller's container.
  • Handle target changes — clean up the previous owned host and move the portal when container changes.
  • Preserve React behavior — context and synthetic events continue through the React tree even though the DOM placement changes.
  • Keep the scope narrow — do not add modal semantics, focus management, a backdrop, target selectors, styling, or a global singleton.