useElementSize()

This hook helps you to dynamically recover the width and the height of an HTML element. Dimensions are updated when resizing the window.

The Hook

1import { RefObject, useCallback, useEffect, useState } from 'react'
2
3// See: https://usehooks-typescript.com/react-hook/use-event-listener
4import { useEventListener } from '~/hooks'
5
6interface Size {
7 width: number
8 height: number
9}
10
11function useElementSize<T extends HTMLElement = HTMLDivElement>(
12 elementRef: RefObject<T>,
13): Size {
14 const [size, setSize] = useState<Size>({
15 width: 0,
16 height: 0,
17 })
18
19 // Prevent too many rendering using useCallback
20 const updateSize = useCallback(() => {
21 const node = elementRef?.current
22 if (node) {
23 setSize({
24 width: node.offsetWidth || 0,
25 height: node.offsetHeight || 0,
26 })
27 }
28 }, [elementRef])
29
30 // Initial size on mount
31 useEffect(() => {
32 updateSize()
33 // eslint-disable-next-line react-hooks/exhaustive-deps
34 }, [])
35
36 useEventListener('resize', updateSize)
37
38 return size
39}
40
41export default useElementSize

Usage

1import React, { useRef } from 'react'
2
3import useElementSize from './useElementSize'
4
5export default function Component() {
6 const squareRef = useRef(null)
7
8 const { width, height } = useElementSize(squareRef)
9
10 return (
11 <>
12 <p>{`the square width is ${width}px and height ${height}px`}</p>
13
14 <div
15 ref={squareRef}
16 style={{
17 width: '50%',
18 paddingTop: '50%',
19 backgroundColor: 'aquamarine',
20 margin: 'auto',
21 }}
22 />
23 </>
24 )
25}

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