Functional BytesFunctional Bytes

Monitor for Resize in JavaScript


Window Size Changes

If it your logic based off of the window size and not specific element sizing, an event listener can be added to the window for the resize event with:

const callback = (evt: UIEvent) => console.log(evt);
window.addEventListener('resize', callback);

When done, be sure to remove the event listener with:

window.removeEventListener('resize', callback);

Watching a Specific Element for Size Changes

For cases where a specific element's size needs to be known, a ResizeObserver can be used. This is helpful for when the window doesn't resize but a element's size does (e.g. reflow due to content being added or removed).

To watch an element, the following can be used:

const testDiv = document.getElementById('test');
const callback = (entries: ResizeObserverEntry[], observer: ResizeObserver) => console.log(entries);
const resizeObserver = new ResizeObserver(callback);
resizeObserver.observe(testDiv);

When done watching an element, it can be unobserved using:

// Only stop watching a single element
resizeObserver.unobserve(testDiv);

// Or Alternatively, all elements can be unobserved using:
resizeObserver.disconnect();

React Hook

This hook is a general purpose resize hook. It can be used to track the resizing of a specific element or when the window itself is resized.

If elementToWatch isn't passed, the whole window will be watched for resize events.

import { useEffect } from 'react';

/**
 * Hookup a resize listener to the window or a target element
 * @param {() => void} callback The callback to call on resize (should be memoized with `useCallback` to avoid re-registering each render)
 * @param {boolean} callOnMount Whether to trigger the callback on mount
 * @param {HTMLElement | undefined} elementToWatch The element to watch for size changes
 */
export default function useOnResize(
  callback: () => void,
  callOnMount: boolean = false,
  elementToWatch?: HTMLElement,
) {
  useEffect(() => {
    // Watch a particular element if specified
    if (elementToWatch) {
      const resizeObserver = new ResizeObserver(callback);
      resizeObserver.observe(elementToWatch);
      if (callOnMount) {
        callback();
      }

      return () => {
        resizeObserver.disconnect();
      };
    }

    // If no element is specified, watch for window size changes
    window.addEventListener('resize', callback);
    if (callOnMount) {
      callback();
    }
    return () => {
      window.removeEventListener('resize', callback);
    };
  }, [callback, callOnMount, elementToWatch]);
}

References