useElementSize()
This hook helps you to dynamically recover the width and the height of an HTML element. Dimensions are updated on load, on mount/un-mount, when resizing the window and when the ref changes.
The Hook
1import { useCallback, useState } from 'react'23// See: https://usehooks-ts.com/react-hook/use-event-listener4import { useEventListener } from '../useEventListener'5// See: https://usehooks-ts.com/react-hook/use-isomorphic-layout-effect6import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect'78interface Size {9 width: number10 height: number11}1213function useElementSize<T extends HTMLElement = HTMLDivElement>(): [14 (node: T | null) => void,15 Size,16] {17 // Mutable values like 'ref.current' aren't valid dependencies18 // because mutating them doesn't re-render the component.19 // Instead, we use a state as a ref to be reactive.20 const [ref, setRef] = useState<T | null>(null)21 const [size, setSize] = useState<Size>({22 width: 0,23 height: 0,24 })2526 // Prevent too many rendering using useCallback27 const handleSize = useCallback(() => {28 setSize({29 width: ref?.offsetWidth || 0,30 height: ref?.offsetHeight || 0,31 })3233 // eslint-disable-next-line react-hooks/exhaustive-deps34 }, [ref?.offsetHeight, ref?.offsetWidth])3536 useEventListener('resize', handleSize)3738 useIsomorphicLayoutEffect(() => {39 handleSize()40 // eslint-disable-next-line react-hooks/exhaustive-deps41 }, [ref?.offsetHeight, ref?.offsetWidth])4243 return [setRef, size]44}4546export default useElementSize
Usage
1import React, { useState } from 'react'23import { useElementSize } from 'usehooks-ts'45export default function Component() {6 const [isVisible, setVisible] = useState(true)7 const [squareRef, { width, height }] = useElementSize()89 const toggleVisibility = () => setVisible(x => !x)1011 return (12 <>13 <p>{`The square width is ${width}px and height ${height}px`}</p>14 <p>Try, resize your window and-or click on the button.</p>1516 <button onClick={toggleVisibility}>17 {isVisible ? 'Hide' : 'Show'} square18 </button>1920 {isVisible && (21 <div22 ref={squareRef}23 style={{24 width: '50%',25 paddingTop: '50%',26 backgroundColor: 'aquamarine',27 margin: 'auto',28 }}29 />30 )}31 </>32 )33}
See a way to make this page better?
Edit there »