Sometimes we need to get access to a react component's width and height properties. In this post we will explore how to create a react hook, which dynamically returns these values on resizing.
Sometimes we need to get access to a react component's width and height properties. In this post, we'll see how we can create a react hook, which dynamically gives us these values on resizing.
As a simple example, we want to create a responsive div displaying its own dimensions upon resizing.
When the window resizes, the dimensions of our div will also change.
Our skeleton for this example is a responsive div with hardcoded values for displaying both width and height.
<!-- We will make use of two main building blocks for our hook: 1. [React Refs](https://reactjs.org/docs/refs-and-the-dom.html) Refs are a way in React.js to access DOM nodes. Our resize hook will use refs to get access to the resizing div element. 2. [useLayoutEffect](https://reactjs.org/docs/refs-and-the-dom.html) This hook is similar to `useEffect`, but fires after all DOM mutations. We will use it to attach our resize listener to the resizing div element. -->export default function Home() { const divWidth = 348 const divHeight = 177 return ( <div style={{ height: '100vh', width: '100vw' }}> <div style={{ margin: '50px', width: '70%', height: '70%', border: '1px solid black', display: 'flex', justifyContent: 'center', alignItems: 'center', }} > Dimensions: {divWidth}w {divHeight}h </div> </div> ) }
We begin by adding a React Ref to the div element.
export default function Home() { const divRef = createRef() // ... return ( <div style={{ height: '100vh', width: '100vw' }}> <div ref={divRef} // ... ></div> </div> ) }
With this divRef we are now able to access the underlying DOM element from our react code via divRef.current.
Next, we'll want to replace the hard-coded values divWidth and divHeight with values returned by a hook. Let's start by creating a dummy hook.
import React, { useState, createRef } from 'react' const useRefDimensions = (ref) => { const [dimensions, setDimensions] = useState({ width: 1, height: 2 }) return dimensions } export default function Home() { const divRef = createRef() const dimensions = useRefDimensions(divRef) // ... return ( <div style={{ height: '100vh', width: '100vw' }}> <div ref={divRef} // ... > Dimensions: {dimensions.width}w {dimensions.height}h </div> </div> ) }
With our ref and hook in place, we are ready to add logic to our hook to analyze the div's dimensions and return those dynamically via the getBoundingClientRect() method on the DOM element.
const useRefDimensions = (ref) => { const [dimensions, setDimensions] = useState({ width: 1, height: 2 }) React.useEffect(() => { if (ref.current) { const { current } = ref const boundingRect = current.getBoundingClientRect() const { width, height } = boundingRect setDimensions({ width: Math.round(width), height: Math.round(height) }) } }, [ref]) return dimensions }
By using an Effect Hook within our hook we calculate and return the ref's dimensions on every resize.
import React, { useState, createRef } from 'react' const useRefDimensions = (ref) => { const [dimensions, setDimensions] = useState({ width: 1, height: 2 }) React.useEffect(() => { if (ref.current) { const { current } = ref const boundingRect = current.getBoundingClientRect() const { width, height } = boundingRect setDimensions({ width: Math.round(width), height: Math.round(height) }) } }, [ref]) return dimensions } export default function Home() { const divRef = createRef() const dimensions = useRefDimensions(divRef) return ( <div style={{ height: '100vh', width: '100vw' }}> <div ref={divRef} style={{ margin: '50px', width: '70%', height: '70%', border: '1px solid black', display: 'flex', justifyContent: 'center', alignItems: 'center', }} > Dimensions: {dimensions.width}w {dimensions.height}h </div> </div> ) }