React hook to determine element width dynamically

February 14, 2023
reacthooksnextjs

One common requirement when working with dynamic layouts is the need to determine the width of an element dynamically. In this post, we will create a React hook that calculates the width of an element dynamically.


Step 1: Initializing the Hook

First, let's create a new file called hooks.js to house our hook. In this file, we'll start by importing the necessary React hooks:

    
/**
 * Gets width for referenced element, recalculates after page resize.
 * 
 * @param {*} ref Element reference.
 * 
 * @returns {number} Element width.
 */
export function getWidth(ref) {
    const [width, setWidth] = useState(false);
    if (typeof window != 'undefined') { // Client only.
        useEffect(() => {
            let recalcWidth = () => {
                let w = ref?.current?.offsetWidth || 0;
                setWidth(w);
            };
            // Recalculate on window resize.
            window.addEventListener('resize', recalcWidth);
        }, [ref]);
    }
    return width ? width : 0;
}
    

Step 2: Understanding the Hook

Let's break down the logic behind the getWidth hook:


  • We begin by initializing the width state variable to 0 using the useState hook. This state variable will hold the current width of the element.
  • The function takes an element reference.
  • Inside the useEffect hook, we define the recalcWidth function. This function calculates the width of the element and updates the width state variable.
  • We attach the recalcWidth function to the resize event of the window object using addEventListener.
  • Additionally, we invoke the handleResize function once to capture the initial width of the element.
  • Finally, we return the width variables from the hook.


Step 3: Using the Hook

Now that our hook is ready, let's see how we can utilize it within a component. Here's an example:

    
import React, { useRef, useEffect } from 'react';
import getWidth from './hooks';

export default function testComponent() {
  const ref = useRef();
  let width = getWidth(ref); // Image width, recalculates on resize.

  useEffect(() {
    // Do something on width change.
  },[width]);

  return (
    <div ref={ref}>
      The width of this element is: {width}px
    </div>
  );
}
    

In the above example, we import and use the getWidth hook. By attaching a reference object to the element and passing it to getWidth we enable the hook to calculate and update the width dynamically. The current width is then displayed inside the component and can be used to trigger a change or event.