| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 | '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<IPortalToFollowElementProps> = ({  portalElem,  children,  controlShow,  controlHide,}) => {  const [isShowContent, { setTrue: showContent, setFalse: hideContent, toggle: toggleContent }] = useBoolean(false)  const [wrapElem, setWrapElem] = useState<HTMLDivElement | null>(null)  useEffect(() => {    if (controlShow)      showContent()  }, [controlShow])  useEffect(() => {    if (controlHide)      hideContent()  }, [controlHide])  // todo use click outside hidden  const triggerElemRef = useRef<HTMLDivElement>(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(        <div style={style as React.CSSProperties}>          {portalElem}        </div>,      )      document.body.appendChild(holder)      setWrapElem(holder)      console.log(holder)    }    else {      wrapElem?.remove?.()      setWrapElem(null)    }  }, [isShowContent])  return (    <div ref={triggerElemRef as React.RefObject<HTMLDivElement>} onClick={toggleContent}>      {children}    </div>  )}export default React.memo(PortalToFollowElement)
 |