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'
2
3import { useEventListener, useIsomorphicLayoutEffect } from 'usehooks-ts'
4
5interface Size {
6 width: number
7 height: number
8}
9
10function useElementSize<T extends HTMLElement = HTMLDivElement>(): [
11 (node: T | null) => void,
12 Size,
13] {
14 // Mutable values like 'ref.current' aren't valid dependencies
15 // because mutating them doesn't re-render the component.
16 // Instead, we use a state as a ref to be reactive.
17 const [ref, setRef] = useState<T | null>(null)
18 const [size, setSize] = useState<Size>({
19 width: 0,
20 height: 0,
21 })
22
23 // Prevent too many rendering using useCallback
24 const handleSize = useCallback(() => {
25 setSize({
26 width: ref?.offsetWidth || 0,
27 height: ref?.offsetHeight || 0,
28 })
29
30 // eslint-disable-next-line react-hooks/exhaustive-deps
31 }, [ref?.offsetHeight, ref?.offsetWidth])
32
33 useEventListener('resize', handleSize)
34
35 useIsomorphicLayoutEffect(() => {
36 handleSize()
37 // eslint-disable-next-line react-hooks/exhaustive-deps
38 }, [ref?.offsetHeight, ref?.offsetWidth])
39
40 return [setRef, size]
41}
42
43export default useElementSize

Usage

1import { useState } from 'react'
2
3import { useElementSize } from 'usehooks-ts'
4
5export default function Component() {
6 const [isVisible, setVisible] = useState(true)
7 const [squareRef, { width, height }] = useElementSize()
8
9 const toggleVisibility = () => setVisible(x => !x)
10
11 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>
15
16 <button onClick={toggleVisibility}>
17 {isVisible ? 'Hide' : 'Show'} square
18 </button>
19
20 {isVisible && (
21 <div
22 ref={squareRef}
23 style={{
24 width: '50%',
25 paddingTop: '50%',
26 backgroundColor: 'aquamarine',
27 margin: 'auto',
28 }}
29 />
30 )}
31 </>
32 )
33}

Edit on CodeSandbox

See a way to make this page better?
Edit there »