react-dimensions, react-measure, react-resize-detector, and react-visibility-sensor are React libraries designed to detect changes in element dimensions or visibility within the browser viewport. They enable developers to build responsive components that adapt to container size changes or trigger actions when elements enter or leave the visible area. While all address layout-related reactivity, they differ significantly in implementation approach, underlying browser APIs, maintenance status, and specific use cases—ranging from simple dimension reporting to viewport visibility tracking.
When building responsive, dynamic UIs in React, you often need to know when an element changes size or becomes visible in the viewport. These four packages — react-dimensions, react-measure, react-resize-detector, and react-visibility-sensor — each tackle parts of this problem, but with different approaches, trade-offs, and current maintenance statuses. Let’s break them down for real-world use.
Before comparing features, it’s critical to address project health:
react-dimensions: Deprecated. The npm page states: "This package is no longer maintained. Please consider using react-resize-detector instead." Do not use in new projects.react-measure: Deprecated. The GitHub repo archive notice says: "This library is no longer maintained. Please use react-resize-observer or similar alternatives." Avoid in new work.react-resize-detector: Actively maintained. Regular updates, supports modern ResizeObserver API with fallbacks.react-visibility-sensor: Not officially deprecated, but last npm publish was in 2020. The GitHub repo shows low recent activity. Use with caution; consider Intersection Observer-based alternatives like @reach/observe-rect or native solutions.💡 Bottom line: For new projects,
react-resize-detectoris the only clearly recommended choice among these four for resize detection. For visibility, evaluate if a lightweight custom hook usingIntersectionObservermight be better.
react-dimensions (Deprecated)Used a higher-order component (HOC) that injected containerWidth and containerHeight as props. Relied on polling or event listeners (not ResizeObserver).
// ❌ DO NOT USE — deprecated
import Dimensions from 'react-dimensions';
const MyComponent = ({ containerWidth, containerHeight }) => (
<div>Size: {containerWidth} x {containerHeight}</div>
);
export default Dimensions()(MyComponent);
react-measure (Deprecated)Provided a render-prop component (<Measure>) that reported client rect dimensions via callback. Used DOM mutation observers and scroll/resize events.
// ❌ DO NOT USE — deprecated
import Measure from 'react-measure';
const MyComponent = () => (
<Measure bounds onResize={({ bounds }) => console.log(bounds)}>
{({ measureRef }) => <div ref={measureRef}>Content</div>}
</Measure>
);
react-resize-detectorOffers both component and hook APIs. Uses ResizeObserver under the hood (with polyfill support). Highly configurable.
// ✅ Recommended for resize detection
import { useResizeDetector } from 'react-resize-detector';
const MyComponent = () => {
const { width, height, ref } = useResizeDetector();
return <div ref={ref}>Size: {width} x {height}</div>;
};
// Or as a component
import ResizeDetector from 'react-resize-detector';
<ResizeDetector handleWidth handleHeight onResize={(width, height) => {}}>
<div>Content</div>
</ResizeDetector>
react-visibility-sensorFocused only on visibility, not dimensions. Used getBoundingClientRect() and scroll/resize listeners to determine if an element is in the viewport.
// ⚠️ Use with caution — outdated
import VisibilitySensor from 'react-visibility-sensor';
const MyComponent = () => (
<VisibilitySensor onChange={(isVisible) => console.log(isVisible)}>
<div>Watch me appear!</div>
</VisibilitySensor>
);
| Feature | react-dimensions | react-measure | react-resize-detector | react-visibility-sensor |
|---|---|---|---|---|
| Resize detection | ✅ (deprecated) | ✅ (deprecated) | ✅ (modern) | ❌ |
| Visibility detection | ❌ | ❌ | ❌ | ✅ (outdated method) |
| Uses ResizeObserver | ❌ | ❌ | ✅ | ❌ |
| Hook API | ❌ | ❌ | ✅ | ❌ |
| Render-prop / HOC | HOC | Render-prop | Component + Hook | Render-prop |
| Active maintenance | ❌ | ❌ | ✅ | ⚠️ (inactive) |
You’re using D3 or Chart.js and need to redraw when the parent div resizes.
react-resize-detectorimport { useResizeDetector } from 'react-resize-detector';
import { useEffect } from 'react';
const ResponsiveChart = () => {
const { width, height, ref } = useResizeDetector();
useEffect(() => {
if (width && height) {
drawChart(width, height); // Your chart logic
}
}, [width, height]);
return <div ref={ref} style={{ width: '100%', height: 400 }} />;
};
You want to load images only when they become visible.
react-visibility-sensor works but is outdatedIntersectionObserver with a custom hook or libraries like react-intersection-observer.// Using react-visibility-sensor (not ideal)
<VisibilitySensor partialVisibility offset={{ bottom: 200 }}>
<img src="image.jpg" alt="lazy" />
</VisibilitySensor>
// Modern alternative (recommended)
import { useInView } from 'react-intersection-observer';
const LazyImage = () => {
const { ref, inView } = useInView({ triggerOnce: true, rootMargin: '200px' });
return <img ref={ref} src={inView ? 'image.jpg' : placeholder} />;
};
You need to know if text overflows its container to show “Read more”.
react-resize-detectorreact-visibility-sensor doesn’t help here.const TruncatedText = ({ text }) => {
const { width, ref: containerRef } = useResizeDetector();
const { width: textWidth, ref: textRef } = useResizeDetector();
const isOverflowing = textWidth > width;
return (
<div ref={containerRef} style={{ width: '100%', overflow: 'hidden' }}>
<span ref={textRef}>{text}</span>
{isOverflowing && <button>Show more</button>}
</div>
);
};
react-dimensions and react-measure used legacy techniques (polling, scroll/resize event listeners) that could cause layout thrashing or miss rapid changes.react-resize-detector leverages ResizeObserver, which is asynchronous, efficient, and fires only when actual layout changes occur.react-visibility-sensor uses getBoundingClientRect() on every scroll/resize, which can hurt performance on complex pages. Modern IntersectionObserver is far more efficient.If you’re maintaining a codebase using deprecated packages:
From react-dimensions → react-resize-detector:
Replace HOC with useResizeDetector hook.
From react-measure → react-resize-detector:
Replace <Measure> render prop with hook or component API.
From react-visibility-sensor → modern alternative:
Consider react-intersection-observer or a minimal custom hook:
// Simple custom visibility hook
function useVisibility(ref, options = {}) {
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
setIsVisible(entry.isIntersecting);
}, options);
if (ref.current) observer.observe(ref.current);
return () => observer.disconnect();
}, [ref, options]);
return isVisible;
}
react-resize-detector. It’s the only actively maintained, modern solution in this group.react-visibility-sensor in new projects. Prefer react-intersection-observer or a lightweight custom hook using the native IntersectionObserver API.react-dimensions or react-measure — they are officially deprecated and lack modern performance optimizations.These tools solve real problems, but the JavaScript ecosystem has evolved. Leverage browser APIs like ResizeObserver and IntersectionObserver through well-maintained wrappers — your app’s performance and maintainability will thank you.
Do not use react-dimensions in new projects — it is officially deprecated according to its npm page, which recommends migrating to react-resize-detector. If you encounter it in legacy code, plan a replacement using modern ResizeObserver-based solutions.
Avoid react-measure for new development as it is deprecated and archived on GitHub. The library relied on older DOM measurement techniques and lacks support for modern ResizeObserver. Migrate existing usage to react-resize-detector or similar maintained alternatives.
Choose react-resize-detector when you need reliable, performant detection of element dimension changes in React. It offers both hook and component APIs, uses the modern ResizeObserver API with polyfill support, and is actively maintained. Ideal for responsive charts, dynamic layouts, or any component that must react to container resizing.
Consider react-visibility-sensor only for simple visibility detection in low-complexity scenarios if you cannot adopt newer alternatives, but be aware it is effectively unmaintained (last update in 2020). For new projects, prefer libraries like react-intersection-observer or a custom hook using the native IntersectionObserver API for better performance and reliability.
React higher-order component to get the dimensions of a wrapper element and pass them as properties to the child element.
v^1.0.0 is for React v0.14 and above. Use ^0.1.0 for React v0.13
Some React components require a width to be set in pixels, and cannot be set to 100%. This is a challenge for responsive design. This component creates a wrapper <div> and sets the width and height to 100%, and then passes the dimensions of this div to your component.
Requires nodejs.
$ npm install react-dimensions
Wraps a react component and adds properties containerHeight and
containerWidth. Useful for responsive design. Properties update on
window resize. Note that the parent element must have either a
height or a width, or nothing will be rendered
Can be used as a higher-order component or as an ES7 class decorator (see examples)
Parameters
options object=
options.getHeight function= A function that is passed an element and returns element
height, where element is the wrapper div. Defaults to (element) => element.clientHeightoptions.getWidth function= A function that is passed an element and returns element
width, where element is the wrapper div. Defaults to (element) => element.clientWidthoptions.containerStyle object= A style object for the <div> that will wrap your component.
The dimensions of this div are what are passed as props to your component. The default style is
{ width: '100%', height: '100%', padding: 0, border: 0 } which will cause the div to fill its
parent in most cases. If you are using a flexbox layout you will want to change this default style.options.className string= Control the class name set on the wrapper <div>options.elementResize boolean= Set true to watch the wrapper div for changes in
size which are not a result of window resizing - e.g. changes to the flexbox and other layout. (optional, default false)Examples
// ES2015
import React from 'react'
import Dimensions from 'react-dimensions'
class MyComponent extends React.Component {
render() (
<div
containerWidth={this.props.containerWidth}
containerHeight={this.props.containerHeight}
>
</div>
)
}
export default Dimensions()(MyComponent) // Enhanced component
// ES5
var React = require('react')
var Dimensions = require('react-dimensions')
var MyComponent = React.createClass({
render: function() {(
<div
containerWidth={this.props.containerWidth}
containerHeight={this.props.containerHeight}
>
</div>
)}
}
module.exports = Dimensions()(MyComponent) // Enhanced component
Returns function A higher-order component that can be
used to enhance a react component Dimensions()(MyComponent)
Returns the underlying wrapped component instance. Useful if you need to access a method or property of the component passed to react-dimensions. Does not currently work for stateless function components see #30
Returns object The wrapped React component instance
Will open a browser window for localhost:9966
npm i && npm i react react-dom && npm start
$ npm test