Responsive components often need their own size, not the window's — a chart that must redraw when its container resizes, a truncation that depends on available width, a virtualized list measuring its viewport. The window resize event can't see element-level changes (a sidebar collapsing, flex reflow), but ResizeObserver can: it watches a specific element and fires when its box changes. useResizeObserver wraps it into a { width, height } hook.
Implement useResizeObserver(elementRef). Observe elementRef.current, and on each change report the content-box size — preferring entry.contentBoxSize (inlineSize/blockSize), falling back to entry.contentRect. Disconnect on cleanup, and no-op when there's no element or no ResizeObserver.
function useResizeObserver(elementRef) {
// returns { width, height }
}
const ref = useRef(null);
const { width, height } = useResizeObserver(ref);
<div ref={ref}><Chart width={width} height={height} /></div>
// redraws whenever the div resizes — sidebar toggle, window resize, flex reflow
const { width } = useResizeObserver(ref);
const columns = width < 480 ? 1 : width < 900 ? 2 : 3; // container queries in JS
new ResizeObserver(cb), observe(node), and disconnect() in cleanup.entry.contentBoxSize[0].inlineSize/.blockSize when present (it can be an array or a single object across engines), else entry.contentRect.width/.height.ref.current is null or ResizeObserver is undefined (SSR / old browsers).resize event never fires for.Unlock the solution & editor
Runnable editor + tests
Solve in the browser with instant Jest feedback.
Detailed solutions
Walkthroughs, edge cases, and complexity notes.
Multi-framework variants
React, Vue, Vanilla, Angular — same question, different stacks.