react-resize-detector vs react-measure vs react-visibility-sensor vs react-dimensions
React Element Resize and Visibility Detection Libraries
react-resize-detectorreact-measurereact-visibility-sensorreact-dimensionsSimilar Packages:
React Element Resize and Visibility Detection Libraries

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.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-resize-detector1,380,4491,30041.1 kB25 months agoMIT
react-measure660,5811,943-305 years agoMIT
react-visibility-sensor184,8702,323-837 years agoMIT
react-dimensions10,713450-298 years agoMIT

React Layout and Visibility Detection: A Deep Dive into react-dimensions, react-measure, react-resize-detector, and react-visibility-sensor

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.

⚠️ Deprecation Status: What’s Still Safe to 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-detector is the only clearly recommended choice among these four for resize detection. For visibility, evaluate if a lightweight custom hook using IntersectionObserver might be better.

📏 Detecting Element Resizes: How Each Package Works

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-detector

Offers 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-sensor

Focused 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>
);

🔍 Core Capabilities Compared

Featurereact-dimensionsreact-measurereact-resize-detectorreact-visibility-sensor
Resize detection✅ (deprecated)✅ (deprecated)✅ (modern)
Visibility detection✅ (outdated method)
Uses ResizeObserver
Hook API
Render-prop / HOCHOCRender-propComponent + HookRender-prop
Active maintenance⚠️ (inactive)

🧪 Real-World Usage Scenarios

Scenario 1: Responsive Chart That Adapts to Container Size

You’re using D3 or Chart.js and need to redraw when the parent div resizes.

  • ✅ Best choice: react-resize-detector
  • Why? Modern, performant, and gives you exact width/height via hooks.
import { 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 }} />;
};

Scenario 2: Lazy-Loading Images When They Enter Viewport

You want to load images only when they become visible.

  • ⚠️ react-visibility-sensor works but is outdated
  • Better: Use native IntersectionObserver 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} />;
};

Scenario 3: Measuring Text Width for Dynamic Truncation

You need to know if text overflows its container to show “Read more”.

  • ✅ Only viable option: react-resize-detector
  • Deprecated packages shouldn’t be used; react-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>
  );
};

🛠️ Performance and Accuracy Considerations

  • 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.

🔄 Migration Path for Legacy Code

If you’re maintaining a codebase using deprecated packages:

  • From react-dimensionsreact-resize-detector: Replace HOC with useResizeDetector hook.

  • From react-measurereact-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;
}

💡 Final Recommendations

  • For resize detection: Use react-resize-detector. It’s the only actively maintained, modern solution in this group.
  • For visibility detection: Avoid react-visibility-sensor in new projects. Prefer react-intersection-observer or a lightweight custom hook using the native IntersectionObserver API.
  • Never start a new project with 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.

How to Choose: react-resize-detector vs react-measure vs react-visibility-sensor vs react-dimensions
  • react-resize-detector:

    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.

  • react-measure:

    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.

  • react-visibility-sensor:

    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-dimensions:

    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.

README for react-resize-detector

Handle element resizes like it's 2025!

Live demo

Modern browsers now have native support for detecting element size changes through ResizeObservers. This library utilizes ResizeObservers to facilitate managing element size changes in React applications.

🐥 Tiny ~2kb

🐼 Written in TypeScript

🐠 Used by 170k repositories

🦄 Produces 100 million downloads annually

No window.resize listeners! No timeouts!

Should you use this library?

Consider CSS Container Queries first! They now work in all major browsers and might solve your use case with pure CSS.

CSS Container Queries Example
<div class="post">
  <div class="card">
    <h2>Card title</h2>
    <p>Card content</p>
  </div>
</div>
.post {
  container-type: inline-size;
}

/* Default heading styles for the card title */
.card h2 {
  font-size: 1em;
}

/* If the container is larger than 700px */
@container (min-width: 700px) {
  .card h2 {
    font-size: 2em;
  }
}

Use this library when you need:

  • JavaScript-based resize logic with full TypeScript support
  • Complex calculations based on dimensions
  • Integration with React state/effects
  • Programmatic control over resize behavior

Installation

npm install react-resize-detector
# OR
yarn add react-resize-detector
# OR
pnpm add react-resize-detector

Quick Start

Basic Usage

import { useResizeDetector } from 'react-resize-detector';

const CustomComponent = () => {
  const { width, height, ref } = useResizeDetector<HTMLDivElement>();
  return <div ref={ref}>{`${width}x${height}`}</div>;
};

With Resize Callback

import { useCallback } from 'react';
import { useResizeDetector, OnResizeCallback } from 'react-resize-detector';

const CustomComponent = () => {
  const onResize: OnResizeCallback = useCallback((payload) => {
    if (payload.width !== null && payload.height !== null) {
      console.log('Dimensions:', payload.width, payload.height);
    } else {
      console.log('Element unmounted');
    }
  }, []);

  const { width, height, ref } = useResizeDetector<HTMLDivElement>({
    onResize,
  });

  return <div ref={ref}>{`${width}x${height}`}</div>;
};

With External Ref (Advanced)

It's not advised to use this approach, as dynamically mounting and unmounting the observed element could lead to unexpected behavior.

import { useRef } from 'react';
import { useResizeDetector } from 'react-resize-detector';

const CustomComponent = () => {
  const targetRef = useRef<HTMLDivElement>(null);
  const { width, height } = useResizeDetector({ targetRef });
  return <div ref={targetRef}>{`${width}x${height}`}</div>;
};

API Reference

Hook Signature

useResizeDetector<T extends HTMLElement = HTMLElement>(
  props?: useResizeDetectorProps<T>
): UseResizeDetectorReturn<T>

Props

PropTypeDescriptionDefault
onResize(payload: ResizePayload) => voidCallback invoked with resize informationundefined
handleWidthbooleanTrigger updates on width changestrue
handleHeightbooleanTrigger updates on height changestrue
skipOnMountbooleanSkip the first resize event when component mountsfalse
disableRerenderbooleanDisable re-renders triggered by the hook. Only the onResize callback will be calledfalse
refreshMode'throttle' | 'debounce'Rate limiting strategy. See es-toolkit docsundefined
refreshRatenumberDelay in milliseconds for rate limiting1000
refreshOptions{ leading?: boolean; trailing?: boolean }Additional options for throttle/debounceundefined
observerOptionsResizeObserverOptionsOptions passed to resizeObserver.observeundefined
targetRefMutableRefObject<T | null>External ref to observe (use with caution)undefined

Advanced Examples

Responsive Component

import { useResizeDetector } from 'react-resize-detector';

const ResponsiveCard = () => {
  const { width, ref } = useResizeDetector();

  const cardStyle = {
    padding: width > 600 ? '2rem' : '1rem',
    fontSize: width > 400 ? '1.2em' : '1em',
    flexDirection: width > 500 ? 'row' : 'column',
  };

  return (
    <div ref={ref} style={cardStyle}>
      <h2>Responsive Card</h2>
      <p>Width: {width}px</p>
    </div>
  );
};

Chart Resizing

import { useResizeDetector } from 'react-resize-detector';
import { useEffect, useRef } from 'react';

const Chart = () => {
  const chartRef = useRef(null);
  const { width, height, ref } = useResizeDetector({
    refreshMode: 'debounce',
    refreshRate: 100,
  });

  useEffect(() => {
    if (width && height && chartRef.current) {
      // Redraw chart with new dimensions
      redrawChart(chartRef.current, width, height);
    }
  }, [width, height]);

  return <canvas ref={ref} />;
};

Performance Optimization

import { useResizeDetector } from 'react-resize-detector';

const OptimizedComponent = () => {
  const { width, height, ref } = useResizeDetector({
    // Only track width changes
    handleHeight: false,
    // Debounce rapid changes
    refreshMode: 'debounce',
    refreshRate: 150,
    // Skip initial mount calculation
    skipOnMount: true,
    // Use border-box for more accurate measurements
    observerOptions: { box: 'border-box' },
  });

  return <div ref={ref}>Optimized: {width}px wide</div>;
};

Disable Re-renders

import { useResizeDetector } from 'react-resize-detector';

const NonRerenderingComponent = () => {
  const { ref } = useResizeDetector({
    // Disable re-renders triggered by the hook
    disableRerender: true,
    // Handle resize events through callback only
    onResize: ({ width, height }) => {
      // Update external state or perform side effects
      // without causing component re-renders
      console.log('Resized to:', width, height);
    },
  });

  return <div ref={ref}>This component won't re-render on resize</div>;
};

Browser Support

  • ✅ Chrome 64+
  • ✅ Firefox 69+
  • ✅ Safari 13.1+
  • ✅ Edge 79+

For older browsers, consider using a ResizeObserver polyfill.

Testing

const { ResizeObserver } = window;

beforeEach(() => {
  delete window.ResizeObserver;
  // Mock ResizeObserver for tests
  window.ResizeObserver = jest.fn().mockImplementation(() => ({
    observe: jest.fn(),
    unobserve: jest.fn(),
    disconnect: jest.fn(),
  }));
});

afterEach(() => {
  window.ResizeObserver = ResizeObserver;
  jest.restoreAllMocks();
});

Performance Tips

  1. Use handleWidth/handleHeight: false if you only need one dimension
  2. Enable skipOnMount: true if you don't need initial measurements
  3. Use debounce or throttle for expensive resize handlers
  4. Specify observerOptions.box for consistent measurements

License

MIT

❤️ Support

Show us some love and STAR ⭐ the project if you find it useful