UNPKG

@atlaskit/portal

Version:

A wrapper for rendering components in React portals.

44 lines (43 loc) 1.86 kB
import React, { Suspense, useState } from 'react'; import { createPortal } from 'react-dom'; import { ThemeProvider } from '@atlaskit/app-provider/theme-provider'; import { useColorMode } from '@atlaskit/app-provider/use-color-mode'; import { useIsInsideThemeProvider } from '@atlaskit/app-provider/use-is-inside-theme-provider'; import { useIsomorphicLayoutEffect } from '../hooks/use-isomorphic-layout-effect'; import { createAtlaskitPortal } from '../utils/create-atlaskit-portal'; import { createPortalParent } from '../utils/create-portal-parent'; export default function InternalPortalNew(props) { const { zIndex, children } = props; const [atlaskitPortal, setAtlaskitPortal] = useState(null); const colorMode = useColorMode(); const isInsideThemeProvider = useIsInsideThemeProvider(); useIsomorphicLayoutEffect(() => { const tempPortalContainer = createAtlaskitPortal(zIndex); setAtlaskitPortal(tempPortalContainer); const portalParent = createPortalParent(); if (!tempPortalContainer || !portalParent) { return; } portalParent.appendChild(tempPortalContainer); return () => { if (tempPortalContainer) { portalParent.removeChild(tempPortalContainer); } setAtlaskitPortal(null); }; }, [zIndex]); /** * We wrap portal children with a Suspense boundary because in React 18 concurrent, * if you suspend from _within_ a portal to a Suspense boundary _outside_ the portal, * our portal gets in an infinite loop of rendering. */ const suspendedChildren = /*#__PURE__*/React.createElement(Suspense, { fallback: null }, isInsideThemeProvider ? /*#__PURE__*/React.createElement(ThemeProvider, { defaultColorMode: colorMode }, children) : children); return atlaskitPortal ? /*#__PURE__*/createPortal(suspendedChildren, atlaskitPortal) : null; }