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]);
}