import React from 'react' type Component = React.ReactElement type ContextType = { outlet: Component | null append(id: string, component: Component): void remove(id: string): void } type ComponentMap = { [id: string]: Component } export const Context = React.createContext({ outlet: null, append: () => {}, remove: () => {}, }) export function Provider(props: React.PropsWithChildren<{}>) { const map = React.useRef({}) const [outlet, setOutlet] = React.useState(null) const append = React.useCallback((id, component) => { if (map.current[id]) return map.current[id] = {component} setOutlet(<>{Object.values(map.current)}) }, []) const remove = React.useCallback(id => { delete map.current[id] setOutlet(<>{Object.values(map.current)}) }, []) return ( {props.children} ) } export function Outlet() { const ctx = React.useContext(Context) return ctx.outlet } export function Portal({children}: React.PropsWithChildren<{}>) { const {append, remove} = React.useContext(Context) const id = React.useId() React.useEffect(() => { append(id, children as Component) return () => remove(id) }, [id, children, append, remove]) return null }