Created
September 15, 2023 08:53
-
-
Save freddi301/7fcf2c919ef8ddd43f48145e9aafb6f9 to your computer and use it in GitHub Desktop.
React hook to measure an element before rendering it
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* React hook to measure an element before rendering it | |
* given some jsx it renders it in a hidden div then measures its size | |
* the hook returns width and height and portal | |
* @important the portal must be in the page to be able to render the hidden div for measurements | |
* @warning the jsx will be renred probably twice, once for measurement, and where you actually use it | |
*/ | |
export function useDomSize(children: JSX.Element) { | |
const [width, setWidth] = React.useState(0); | |
const [height, setHeight] = React.useState(0); | |
const invisibleContainer = React.useMemo(() => { | |
const element = document.createElement("div"); | |
element.style.position = "fixed"; | |
element.style.top = "-10000px"; | |
element.style.left = "-10000px"; | |
return element; | |
}, []); | |
(window as any).prova = invisibleContainer; | |
const portal = ReactDOM.createPortal(children, invisibleContainer); | |
React.useLayoutEffect(() => { | |
document.body.appendChild(invisibleContainer); | |
return () => { | |
document.body.removeChild(invisibleContainer); | |
}; | |
}, [invisibleContainer]); | |
React.useLayoutEffect(() => { | |
const { width, height } = invisibleContainer.getBoundingClientRect(); | |
setWidth(width); | |
setHeight(height); | |
}, [children, invisibleContainer]); | |
return { portal, width, height }; | |
} | |
function Example() { | |
const tooltip = ( | |
<p> | |
Helloworld | |
<br /> | |
</p> | |
); | |
const tooltipDimensions = useDomSize(tooltip); | |
return ( | |
<React.Fragment> | |
{tooltip} | |
{tooltipDimensions.portal} | |
{tooltipDimensions.width} {tooltipDimensions.height} | |
</React.Fragment> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment