import { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; function createWrapperAndAppendToBody(wrapperId: string) { const wrapperElement = document.createElement('div'); wrapperElement.setAttribute('id', wrapperId); document.body.appendChild(wrapperElement); return wrapperElement; } type Props = { children: React.ReactNode; wrapperId: string; }; export const ReactPortal: React.FC = ({ children, wrapperId = 'react-portal-wrapper' }) => { const [wrapperElement, setWrapperElement] = useState( null ); useEffect(() => { let element = document.getElementById(wrapperId) as HTMLElement; let modalCreated = false; if (!element) { modalCreated = true; element = createWrapperAndAppendToBody(wrapperId); } setWrapperElement(element); return () => { // delete the programatically created element if it was created if (modalCreated && element.parentNode) { element.parentNode.removeChild(element); } }; }, [wrapperId]); if (wrapperElement === null) return null; return createPortal(children, wrapperElement); };