0
# Performance Tools
1
2
Development and performance utilities including pure render mixins and performance measurement tools.
3
4
## Capabilities
5
6
### Pure Render Mixin
7
8
Performance optimization mixin that implements shallow comparison for shouldComponentUpdate.
9
10
```javascript { .api }
11
/**
12
* Mixin that provides shallow comparison for shouldComponentUpdate
13
*/
14
const PureRenderMixin = {
15
/**
16
* Shallow comparison implementation for props and state
17
* @param {object} nextProps - Next props object
18
* @param {object} nextState - Next state object
19
* @returns {boolean} Whether component should update
20
*/
21
shouldComponentUpdate(nextProps, nextState);
22
};
23
```
24
25
**Usage Examples:**
26
27
```javascript
28
import { PureRenderMixin } from 'preact-compat';
29
// or
30
import PureRenderMixin from 'preact-compat/lib/ReactComponentWithPureRenderMixin';
31
32
// With createClass
33
const OptimizedComponent = createClass({
34
mixins: [PureRenderMixin],
35
36
render() {
37
return (
38
<div>
39
<h1>{this.props.title}</h1>
40
<p>{this.props.content}</p>
41
</div>
42
);
43
}
44
});
45
46
// Manual implementation in ES6 class
47
class ManualPureComponent extends Component {
48
shouldComponentUpdate(nextProps, nextState) {
49
return PureRenderMixin.shouldComponentUpdate.call(
50
this,
51
nextProps,
52
nextState
53
);
54
}
55
56
render() {
57
return <div>{this.props.data}</div>;
58
}
59
}
60
61
// Or use PureComponent (recommended)
62
class BetterPureComponent extends PureComponent {
63
render() {
64
return <div>{this.props.data}</div>;
65
}
66
}
67
```
68
69
### Performance Measurement (ReactPerf)
70
71
Development tools for measuring component performance (no-op implementations in production).
72
73
```javascript { .api }
74
/**
75
* Performance measurement utilities (no-op in Preact)
76
*/
77
const ReactPerf = {
78
/**
79
* Start performance measurement
80
*/
81
start(): void;
82
83
/**
84
* Stop performance measurement
85
*/
86
stop(): void;
87
88
/**
89
* Check if profiling is currently running
90
* @returns {boolean} Always false in Preact
91
*/
92
isRunning(): boolean;
93
94
/**
95
* Get last measurement data
96
* @returns {Array} Empty array in Preact
97
*/
98
getLastMeasurements(): Array<any>;
99
100
/**
101
* Get exclusive time measurements
102
* @param {Array} measurements - Measurement data
103
* @returns {Array} Empty array in Preact
104
*/
105
getExclusive(measurements): Array<any>;
106
107
/**
108
* Get inclusive time measurements
109
* @param {Array} measurements - Measurement data
110
* @returns {Array} Empty array in Preact
111
*/
112
getInclusive(measurements): Array<any>;
113
114
/**
115
* Get wasted time measurements
116
* @param {Array} measurements - Measurement data
117
* @returns {Array} Empty array in Preact
118
*/
119
getWasted(measurements): Array<any>;
120
121
/**
122
* Get operation measurements
123
* @param {Array} measurements - Measurement data
124
* @returns {Array} Empty array in Preact
125
*/
126
getOperations(measurements): Array<any>;
127
128
/**
129
* Print exclusive time measurements (no-op)
130
* @param {Array} measurements - Measurement data
131
*/
132
printExclusive(measurements): void;
133
134
/**
135
* Print inclusive time measurements (no-op)
136
* @param {Array} measurements - Measurement data
137
*/
138
printInclusive(measurements): void;
139
140
/**
141
* Print wasted time measurements (no-op)
142
* @param {Array} measurements - Measurement data
143
*/
144
printWasted(measurements): void;
145
146
/**
147
* Print operation measurements (no-op)
148
* @param {Array} measurements - Measurement data
149
*/
150
printOperations(measurements): void;
151
};
152
```
153
154
**Usage Examples:**
155
156
```javascript
157
import { ReactPerf } from 'preact-compat';
158
// or
159
import ReactPerf from 'preact-compat/lib/ReactPerf';
160
161
// Performance measurement (no-op in Preact, but compatible API)
162
if (process.env.NODE_ENV === 'development') {
163
// Start profiling
164
ReactPerf.start();
165
166
// ... perform operations to measure
167
168
// Stop profiling and collect results
169
ReactPerf.stop();
170
const measurements = ReactPerf.getLastMeasurements();
171
172
// Print different types of measurements
173
ReactPerf.printInclusive(measurements);
174
ReactPerf.printExclusive(measurements);
175
ReactPerf.printWasted(measurements);
176
ReactPerf.printOperations(measurements);
177
178
// Check if profiling is running
179
console.log('Profiling active:', ReactPerf.isRunning());
180
}
181
```
182
183
### Transition Event Utilities
184
185
Utilities for handling CSS transition and animation events.
186
187
```javascript { .api }
188
/**
189
* Add event listener for transition/animation end events
190
* @param {Element} node - DOM element
191
* @param {function} eventListener - Event handler function
192
*/
193
function addEndEventListener(node, eventListener);
194
195
/**
196
* Remove event listener for transition/animation end events
197
* @param {Element} node - DOM element
198
* @param {function} eventListener - Event handler function
199
*/
200
function removeEndEventListener(node, eventListener);
201
```
202
203
**Usage Examples:**
204
205
```javascript
206
import {
207
addEndEventListener,
208
removeEndEventListener
209
} from 'preact-compat/lib/ReactTransitionEvents';
210
211
class AnimatedComponent extends Component {
212
componentDidMount() {
213
const element = this.refs.animatedElement;
214
215
// Add transition end listener
216
this.handleTransitionEnd = (event) => {
217
console.log('Transition completed:', event);
218
this.setState({ animationComplete: true });
219
};
220
221
addEndEventListener(element, this.handleTransitionEnd);
222
}
223
224
componentWillUnmount() {
225
const element = this.refs.animatedElement;
226
removeEndEventListener(element, this.handleTransitionEnd);
227
}
228
229
startAnimation = () => {
230
const element = this.refs.animatedElement;
231
element.classList.add('animate');
232
};
233
234
render() {
235
return (
236
<div>
237
<div
238
ref="animatedElement"
239
className="animated-box"
240
style={{
241
width: '100px',
242
height: '100px',
243
background: 'blue',
244
transition: 'transform 0.3s ease'
245
}}
246
/>
247
<button onClick={this.startAnimation}>
248
Start Animation
249
</button>
250
</div>
251
);
252
}
253
}
254
```
255
256
### Mount/Unmount Utilities
257
258
```javascript { .api }
259
/**
260
* Unmount component from DOM node
261
* @param {Element} container - DOM container element
262
* @returns {boolean} True if component was unmounted
263
*/
264
function unmountComponentAtNode(container);
265
```
266
267
**Usage Examples:**
268
269
```javascript
270
import { unmountComponentAtNode } from 'preact-compat';
271
// or
272
import { unmountComponentAtNode } from 'preact-compat/lib/ReactMount';
273
274
// Clean up component
275
const container = document.getElementById('app');
276
const wasUnmounted = unmountComponentAtNode(container);
277
278
if (wasUnmounted) {
279
console.log('Component successfully unmounted');
280
} else {
281
console.log('No component was mounted in container');
282
}
283
```
284
285
### Performance Best Practices
286
287
```javascript
288
import { PureComponent } from 'preact-compat';
289
290
// Use PureComponent for components with simple props
291
class OptimizedListItem extends PureComponent {
292
render() {
293
const { item, onSelect } = this.props;
294
return (
295
<div onClick={() => onSelect(item.id)}>
296
{item.name}
297
</div>
298
);
299
}
300
}
301
302
// Memoize expensive computations outside render
303
class ExpensiveComponent extends PureComponent {
304
constructor(props) {
305
super(props);
306
this.memoizedResult = null;
307
this.lastInput = null;
308
}
309
310
expensiveCalculation = (input) => {
311
if (this.lastInput === input && this.memoizedResult !== null) {
312
return this.memoizedResult;
313
}
314
315
// Simulate expensive calculation
316
const result = input.split('').reverse().join('').repeat(1000);
317
this.memoizedResult = result;
318
this.lastInput = input;
319
return result;
320
};
321
322
render() {
323
const result = this.expensiveCalculation(this.props.input);
324
return <div>{result.substring(0, 100)}...</div>;
325
}
326
}
327
328
// Use keys for dynamic lists
329
class DynamicList extends Component {
330
render() {
331
return (
332
<div>
333
{this.props.items.map(item => (
334
<OptimizedListItem
335
key={item.id} // Important for performance
336
item={item}
337
onSelect={this.props.onSelect}
338
/>
339
))}
340
</div>
341
);
342
}
343
}
344
```
345
346
## Import Patterns
347
348
```javascript
349
// Main imports
350
import { PureRenderMixin, ReactPerf } from 'preact-compat';
351
352
// Specific library imports
353
import PureRenderMixin from 'preact-compat/lib/ReactComponentWithPureRenderMixin';
354
import ReactPerf from 'preact-compat/lib/ReactPerf';
355
import { addEndEventListener, removeEndEventListener } from 'preact-compat/lib/ReactTransitionEvents';
356
import { unmountComponentAtNode } from 'preact-compat/lib/ReactMount';
357
358
// CommonJS
359
const { PureRenderMixin, ReactPerf } = require('preact-compat');
360
```
361
362
## Types
363
364
```javascript { .api }
365
interface PureRenderMixinType {
366
shouldComponentUpdate(nextProps: object, nextState: object): boolean;
367
}
368
369
interface ReactPerfType {
370
start(): void;
371
stop(): void;
372
isRunning(): boolean;
373
getLastMeasurements(): Array<any>;
374
getExclusive(measurements: Array<any>): Array<any>;
375
getInclusive(measurements: Array<any>): Array<any>;
376
getWasted(measurements: Array<any>): Array<any>;
377
getOperations(measurements: Array<any>): Array<any>;
378
printExclusive(measurements: Array<any>): void;
379
printInclusive(measurements: Array<any>): void;
380
printWasted(measurements: Array<any>): void;
381
printOperations(measurements: Array<any>): void;
382
}
383
384
type TransitionEventListener = (event: TransitionEvent | AnimationEvent) => void;
385
386
interface TransitionEventUtils {
387
addEndEventListener(node: Element, eventListener: TransitionEventListener): void;
388
removeEndEventListener(node: Element, eventListener: TransitionEventListener): void;
389
}
390
```