React hook utility for measuring DOM element boundaries with reactive updates
npx @tessl/cli install tessl/npm-react-use-measure@2.1.00
# React Use Measure
1
2
React Use Measure is a utility React hook for measuring DOM element boundaries with reactive updates. It provides precise position and size information that accounts for scroll containers and viewport changes, solving the common problem of getting accurate element positioning in dynamic React applications.
3
4
## Package Information
5
6
- **Package Name**: react-use-measure
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install react-use-measure`
10
11
## Core Imports
12
13
```typescript
14
import useMeasure from "react-use-measure";
15
import type { RectReadOnly, Options } from "react-use-measure";
16
```
17
18
For CommonJS:
19
20
```javascript
21
const useMeasure = require("react-use-measure");
22
// For accessing the default export specifically:
23
// const useMeasure = require("react-use-measure").default;
24
```
25
26
## Basic Usage
27
28
```typescript
29
import React from "react";
30
import useMeasure from "react-use-measure";
31
32
function MyComponent() {
33
const [ref, bounds] = useMeasure();
34
35
return (
36
<div>
37
<div ref={ref}>
38
Measure me!
39
</div>
40
<p>
41
Size: {bounds.width}x{bounds.height}
42
Position: ({bounds.left}, {bounds.top})
43
</p>
44
</div>
45
);
46
}
47
```
48
49
## Architecture
50
51
React Use Measure is built around several key components:
52
53
- **ResizeObserver Integration**: Uses the browser's ResizeObserver API to detect element size changes
54
- **Scroll Tracking**: Optional monitoring of scroll events in nested containers and viewport
55
- **Debouncing System**: Configurable debouncing for performance optimization
56
- **Polyfill Support**: Injectable ResizeObserver polyfill for older browsers
57
- **Reactive Updates**: Automatic state updates when element bounds change
58
59
## Capabilities
60
61
### Main Hook Function
62
63
The primary useMeasure hook provides DOM element measurement with reactive updates.
64
65
```typescript { .api }
66
/**
67
* React hook for measuring DOM element boundaries with reactive updates
68
* @param options - Configuration options for measurement behavior (defaults: { debounce: 0, scroll: false, offsetSize: false })
69
* @returns Tuple containing ref callback, bounds object, and force refresh function
70
*/
71
function useMeasure(options?: Options): [
72
(element: HTMLOrSVGElement | null) => void,
73
RectReadOnly,
74
() => void
75
];
76
```
77
78
**Usage Example:**
79
80
```typescript
81
import useMeasure from "react-use-measure";
82
83
function ResponsiveComponent() {
84
const [ref, bounds, forceRefresh] = useMeasure({
85
debounce: 100,
86
scroll: true
87
});
88
89
// Use forceRefresh to manually trigger measurement
90
const handleRefresh = () => {
91
forceRefresh();
92
};
93
94
return (
95
<div>
96
<div ref={ref}>Content to measure</div>
97
<button onClick={handleRefresh}>Force Refresh</button>
98
</div>
99
);
100
}
101
```
102
103
### Advanced Configuration
104
105
Configure measurement behavior with debouncing, scroll tracking, and polyfill support.
106
107
```typescript { .api }
108
interface Options {
109
/** Debounce events in milliseconds or separate values for scroll/resize (default: 0) */
110
debounce?: number | { scroll: number; resize: number };
111
/** React to nested scroll changes - use with caution for performance (default: false) */
112
scroll?: boolean;
113
/** Inject a ResizeObserver polyfill for browser compatibility */
114
polyfill?: { new (cb: ResizeObserverCallback): ResizeObserver };
115
/** Use offsetWidth/offsetHeight instead of getBoundingClientRect for sizing (default: false) */
116
offsetSize?: boolean;
117
}
118
```
119
120
**Usage Example:**
121
122
```typescript
123
import useMeasure from "react-use-measure";
124
import { ResizeObserver } from "@juggle/resize-observer";
125
126
function AdvancedComponent() {
127
const [ref, bounds] = useMeasure({
128
debounce: { scroll: 50, resize: 100 },
129
scroll: true,
130
polyfill: ResizeObserver,
131
offsetSize: true
132
});
133
134
return <div ref={ref}>Advanced measurement</div>;
135
}
136
```
137
138
### Scroll Tracking
139
140
Enable scroll tracking to get accurate positioning within scroll containers.
141
142
```typescript
143
// Enable scroll tracking for elements within scrollable containers
144
const [ref, bounds] = useMeasure({ scroll: true });
145
146
// With scroll tracking, bounds.top and bounds.left account for:
147
// - Page scroll position
148
// - Nested scroll container positions
149
// - Viewport changes
150
```
151
152
### Debouncing Control
153
154
Control performance with debouncing options for scroll and resize events.
155
156
```typescript
157
// Simple debouncing - same value for both scroll and resize
158
const [ref, bounds] = useMeasure({ debounce: 100 });
159
160
// Separate debouncing for scroll vs resize events
161
const [ref, bounds] = useMeasure({
162
debounce: { scroll: 50, resize: 200 }
163
});
164
165
// No debouncing for immediate updates
166
const [ref, bounds] = useMeasure({ debounce: 0 });
167
```
168
169
## Types
170
171
### Bounds Object
172
173
```typescript { .api }
174
interface RectReadOnly {
175
/** X coordinate relative to viewport */
176
readonly x: number;
177
/** Y coordinate relative to viewport */
178
readonly y: number;
179
/** Element width in pixels */
180
readonly width: number;
181
/** Element height in pixels */
182
readonly height: number;
183
/** Distance from top edge of viewport */
184
readonly top: number;
185
/** Distance from right edge of viewport */
186
readonly right: number;
187
/** Distance from bottom edge of viewport */
188
readonly bottom: number;
189
/** Distance from left edge of viewport */
190
readonly left: number;
191
/** Index signature for additional numeric properties */
192
[key: string]: number;
193
}
194
```
195
196
### Hook Return Type
197
198
```typescript { .api }
199
/** The return type of the useMeasure hook */
200
type UseMeasureResult = [
201
/** Ref callback to attach to the element you want to measure */
202
(element: HTMLOrSVGElement | null) => void,
203
/** Current bounds/measurements of the element */
204
RectReadOnly,
205
/** Function to manually trigger a measurement update */
206
() => void
207
];
208
```
209
210
### Element Type Alias
211
212
```typescript { .api }
213
/** Union type for HTML and SVG elements that can be measured */
214
type HTMLOrSVGElement = HTMLElement | SVGElement;
215
```
216
217
### ResizeObserver Types
218
219
```typescript { .api }
220
/** ResizeObserver callback function type */
221
type ResizeObserverCallback = (entries: any[], observer: ResizeObserver) => void;
222
223
/** ResizeObserver class declaration for polyfill compatibility */
224
declare class ResizeObserver {
225
constructor(callback: ResizeObserverCallback);
226
observe(target: Element, options?: any): void;
227
unobserve(target: Element): void;
228
disconnect(): void;
229
static toString(): string;
230
}
231
```
232
233
## Error Handling
234
235
The hook throws a descriptive error when ResizeObserver is not available:
236
237
```typescript
238
// This will throw if ResizeObserver is not supported and no polyfill is provided
239
const [ref, bounds] = useMeasure();
240
241
// Error message: "This browser does not support ResizeObserver out of the box.
242
// See: https://github.com/react-spring/react-use-measure/#resize-observer-polyfills"
243
244
// Solution: Provide a polyfill
245
import { ResizeObserver } from "@juggle/resize-observer";
246
const [ref, bounds] = useMeasure({ polyfill: ResizeObserver });
247
```
248
249
## Performance Considerations
250
251
- **Debouncing**: Use debouncing for frequently changing elements to avoid excessive re-renders
252
- **Scroll Tracking**: Only enable scroll tracking when necessary, as it adds event listeners
253
- **Initial Render**: Bounds will be zero on first render until the element is measured
254
- **Memory Leaks**: The hook automatically cleans up observers and event listeners on unmount
255
256
## Browser Compatibility
257
258
- **Modern Browsers**: Works out of the box with native ResizeObserver support
259
- **Older Browsers**: Requires ResizeObserver polyfill (recommended: @juggle/resize-observer)
260
- **React Version**: Requires React 16.13 or higher
261
- **React-DOM**: Optional peer dependency for SSR environments