Card title
Card content
React resize detector
npm install react-resize-detectorwindow.resize listeners! No timeouts!
html
Card title
Card content
`
`css
.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;
}
}
`
bash
npm install react-resize-detector
OR
yarn add react-resize-detector
OR
pnpm add react-resize-detector
`
Quick Start
$3
`tsx
import { useResizeDetector } from 'react-resize-detector';
const CustomComponent = () => {
const { width, height, ref } = useResizeDetector();
return {${width}x${height}};
};
`
$3
`tsx
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({
onResize,
});
return {${width}x${height}};
};
`
$3
_It's not advised to use this approach, as dynamically mounting and unmounting the observed element could lead to unexpected behavior._
`tsx
import { useRef } from 'react';
import { useResizeDetector } from 'react-resize-detector';
const CustomComponent = () => {
const targetRef = useRef(null);
const { width, height } = useResizeDetector({ targetRef });
return {${width}x${height}};
};
`
API Reference
$3
`typescript
useResizeDetector(
props?: useResizeDetectorProps
): UseResizeDetectorReturn
`
$3
| Prop | Type | Description | Default |
| ----------------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------- |
| onResize | (payload: ResizePayload) => void | Callback invoked with resize information | undefined |
| handleWidth | boolean | Trigger updates on width changes | true |
| handleHeight | boolean | Trigger updates on height changes | true |
| skipOnMount | boolean | Skip the first resize event when component mounts | false |
| disableRerender | boolean | Disable re-renders triggered by the hook. Only the onResize callback will be called | false |
| refreshMode | 'throttle' \| 'debounce' | Rate limiting strategy. See es-toolkit docs | undefined |
| refreshRate | number | Delay in milliseconds for rate limiting | 1000 |
| refreshOptions | { leading?: boolean; trailing?: boolean } | Additional options for throttle/debounce | undefined |
| observerOptions | ResizeObserverOptions | Options passed to resizeObserver.observe | undefined |
| targetRef | MutableRefObject | External ref to observe (use with caution) | undefined |
Advanced Examples
$3
`jsx
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 (
Responsive Card
Width: {width}px
);
};
`
$3
`jsx
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 ;
};
`
$3
`jsx
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 Optimized: {width}px wide;
};
`
$3
`jsx
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 This component won't re-render on resize;
};
`
Browser Support
- ā
Chrome 64+
- ā
Firefox 69+
- ā
Safari 13.1+
- ā
Edge 79+
For older browsers, consider using a ResizeObserver polyfill.
Testing
`jsx
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