'use client' import { useBoolean } from 'ahooks' import React, { useEffect, useRef, useState } from 'react' import type { FC } from 'react' import { createRoot } from 'react-dom/client' type IPortalToFollowElementProps = { portalElem: React.ReactNode children: React.ReactNode controlShow?: number controlHide?: number } const PortalToFollowElement: FC = ({ portalElem, children, controlShow, controlHide, }) => { const [isShowContent, { setTrue: showContent, setFalse: hideContent, toggle: toggleContent }] = useBoolean(false) const [wrapElem, setWrapElem] = useState(null) useEffect(() => { if (controlShow) showContent() }, [controlShow]) useEffect(() => { if (controlHide) hideContent() }, [controlHide]) // todo use click outside hidden const triggerElemRef = useRef(null) const calLoc = () => { const triggerElem = triggerElemRef.current if (!triggerElem) { return { display: 'none', } } const { left: triggerLeft, top: triggerTop, height, } = triggerElem.getBoundingClientRect() return { position: 'fixed', left: triggerLeft, top: triggerTop + height, zIndex: 999, } } useEffect(() => { if (isShowContent) { const holder = document.createElement('div') const root = createRoot(holder) const style = calLoc() root.render(
{portalElem}
, ) document.body.appendChild(holder) setWrapElem(holder) console.log(holder) } else { wrapElem?.remove?.() setWrapElem(null) } }, [isShowContent]) return (
} onClick={toggleContent}> {children}
) } export default React.memo(PortalToFollowElement)