Skip to content

Instantly share code, notes, and snippets.

@tlux
Last active August 6, 2025 19:57
Show Gist options
  • Save tlux/bc063f2706e10d68e1073c6fd34d6bb3 to your computer and use it in GitHub Desktop.
Save tlux/bc063f2706e10d68e1073c6fd34d6bb3 to your computer and use it in GitHub Desktop.
React Portal that is mounted as soon as the target element appears in the DOM
import { type PropsWithChildren, useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
type PortalProps = PropsWithChildren & { targetId: string };
export function Portal({ children, targetId }: PortalProps) {
const [targetElement, setTargetElement] = useState<HTMLElement | null>(null);
useEffect(() => {
const updateTargetElement = () => {
setTargetElement(document.getElementById(targetId));
};
updateTargetElement();
const observer = new MutationObserver(() => {
updateTargetElement();
});
observer.observe(document.body, { childList: true, subtree: true });
return () => observer.disconnect();
}, [targetId]);
if (!targetElement) return null;
return createPortal(children, targetElement);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment