0
# React CountUp
1
2
React CountUp is a configurable React component wrapper around CountUp.js that provides animated number counting effects. It offers both declarative component usage and imperative hook-based control with full TypeScript support.
3
4
## Package Information
5
6
- **Package Name**: react-countup
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install react-countup`
10
11
## Core Imports
12
13
```typescript
14
import CountUp, { useCountUp, type CountUpProps } from "react-countup";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const CountUp = require("react-countup").default;
21
const { useCountUp } = require("react-countup");
22
```
23
24
## Basic Usage
25
26
```typescript
27
import React from "react";
28
import CountUp from "react-countup";
29
30
// Simple declarative usage
31
function App() {
32
return (
33
<div>
34
<CountUp end={100} duration={2} />
35
</div>
36
);
37
}
38
39
// With custom formatting
40
function FormattedCounter() {
41
return (
42
<CountUp
43
start={0}
44
end={1234567}
45
duration={3}
46
separator=","
47
prefix="$"
48
suffix=" USD"
49
decimals={2}
50
/>
51
);
52
}
53
```
54
55
## Architecture
56
57
React CountUp is built around three key components:
58
59
- **CountUp Component**: Declarative React component supporting both standard rendering and render prop patterns
60
- **useCountUp Hook**: Imperative hook providing programmatic control over animations with lifecycle management
61
- **CountUp.js Integration**: Leverages the underlying CountUp.js library with React-specific optimizations and SSR compatibility
62
63
## Capabilities
64
65
### CountUp Component
66
67
React component wrapper providing declarative animated counting with extensive customization options and render prop support.
68
69
```typescript { .api }
70
/**
71
* React component for animated number counting
72
*/
73
declare const CountUp: React.FC<CountUpProps>;
74
75
interface CountUpProps extends CommonProps, CallbackProps {
76
/** CSS class name for the container element */
77
className?: string;
78
/** Force redraw on every prop change */
79
redraw?: boolean;
80
/** Render prop function for custom rendering */
81
children?: (props: RenderCounterProps) => React.ReactNode;
82
/** Inline styles for the container element */
83
style?: React.CSSProperties;
84
/** Preserve current value when updating end value */
85
preserveValue?: boolean;
86
/** Additional props for the container span element */
87
containerProps?: React.ComponentPropsWithoutRef<'span'>;
88
}
89
90
interface RenderCounterProps extends CountUpApi {
91
/** Ref to attach to custom render element */
92
countUpRef: React.RefObject<HTMLElement>;
93
}
94
```
95
96
**Usage Examples:**
97
98
```typescript
99
import React from "react";
100
import CountUp from "react-countup";
101
102
// Standard usage
103
<CountUp end={100} duration={2} />
104
105
// With render prop for custom styling
106
<CountUp end={100} duration={2}>
107
{({ countUpRef, start, reset }) => (
108
<div>
109
<span ref={countUpRef} className="big-number" />
110
<button onClick={start}>Start</button>
111
<button onClick={reset}>Reset</button>
112
</div>
113
)}
114
</CountUp>
115
116
// With event callbacks
117
<CountUp
118
end={100}
119
duration={2}
120
onEnd={({ reset, start }) => console.log("Animation completed!")}
121
onStart={() => console.log("Animation started!")}
122
/>
123
```
124
125
### useCountUp Hook
126
127
Hook providing imperative control over CountUp animations with lifecycle management and programmatic API access.
128
129
```typescript { .api }
130
/**
131
* Hook for imperative CountUp control
132
* @param props Configuration options for the counter
133
* @returns API object with control methods
134
*/
135
function useCountUp(props: UseCountUpProps): CountUpApi;
136
137
interface UseCountUpProps extends CommonProps, CallbackProps {
138
/** Target element reference (string selector or React ref) */
139
ref: string | React.RefObject<HTMLElement>;
140
/** Whether to reinitialize when props change */
141
enableReinitialize?: boolean;
142
}
143
144
interface CountUpApi {
145
/** Start or restart the animation */
146
start: () => void;
147
/** Pause or resume the animation */
148
pauseResume: () => void;
149
/** Reset the counter to start value */
150
reset: () => void;
151
/** Update the end value and animate to it */
152
update: (newEnd: string | number) => void;
153
/** Get the underlying CountUp.js instance */
154
getCountUp: (recreate?: boolean) => CountUpInstance;
155
}
156
```
157
158
**Usage Examples:**
159
160
```typescript
161
import React, { useRef } from "react";
162
import { useCountUp } from "react-countup";
163
164
function CustomCounter() {
165
const countUpRef = useRef<HTMLSpanElement>(null);
166
167
const { start, reset, update, pauseResume } = useCountUp({
168
ref: countUpRef,
169
end: 100,
170
duration: 2,
171
startOnMount: false,
172
});
173
174
return (
175
<div>
176
<span ref={countUpRef} />
177
<button onClick={start}>Start</button>
178
<button onClick={pauseResume}>Pause/Resume</button>
179
<button onClick={reset}>Reset</button>
180
<button onClick={() => update(200)}>Update to 200</button>
181
</div>
182
);
183
}
184
185
// With string selector
186
function SelectorCounter() {
187
useCountUp({
188
ref: 'counter-element',
189
end: 100,
190
duration: 2,
191
});
192
193
return <div id="counter-element" />;
194
}
195
```
196
197
## Common Configuration
198
199
### Core Props Interface
200
201
Shared configuration options available to both component and hook.
202
203
```typescript { .api }
204
interface CommonProps extends CountUpInstanceProps {
205
/** Whether to start animation on mount */
206
startOnMount?: boolean;
207
/** Delay before starting animation (in seconds) */
208
delay?: number | null;
209
}
210
211
interface CountUpInstanceProps extends CountUpOptions {
212
/** Number of decimal places to display */
213
decimals?: number;
214
/** The target end value */
215
end: number;
216
/** The starting value */
217
start?: number;
218
/** Whether to use easing animation */
219
useEasing?: boolean;
220
}
221
```
222
223
### Event Callbacks
224
225
Complete event callback system for animation lifecycle management.
226
227
```typescript { .api }
228
interface CallbackProps {
229
/** Called when animation ends */
230
onEnd?: OnEndCallback;
231
/** Called when animation starts */
232
onStart?: OnStartCallback;
233
/** Called when animation is paused/resumed */
234
onPauseResume?: OnPauseResumeCallback;
235
/** Called when counter is reset */
236
onReset?: OnResetCallback;
237
/** Called when end value is updated */
238
onUpdate?: OnUpdateCallback;
239
}
240
241
type OnEndCallback = (args: OnEndArgs) => void;
242
type OnStartCallback = (args: OnStartArgs) => void;
243
type OnPauseResumeCallback = (args: OnPauseResumeArgs) => void;
244
type OnResetCallback = (args: OnResetArgs) => void;
245
type OnUpdateCallback = (args: OnUpdateArgs) => void;
246
247
interface OnEndArgs {
248
pauseResume: () => void;
249
reset: () => void;
250
start: () => void;
251
update: (newEnd: string | number) => void;
252
}
253
254
interface OnStartArgs {
255
pauseResume: () => void;
256
reset: () => void;
257
update: (newEnd: string | number) => void;
258
}
259
260
interface OnPauseResumeArgs {
261
reset: () => void;
262
start: () => void;
263
update: (newEnd: string | number) => void;
264
}
265
266
interface OnResetArgs {
267
pauseResume: () => void;
268
start: () => void;
269
update: (newEnd: string | number) => void;
270
}
271
272
interface OnUpdateArgs {
273
pauseResume: () => void;
274
reset: () => void;
275
start: () => void;
276
}
277
```
278
279
### CountUp.js Configuration Options
280
281
All configuration options from the underlying CountUp.js library are supported:
282
283
```typescript { .api }
284
interface CountUpOptions {
285
/** Decimal character */
286
decimal?: string;
287
/** Thousands separator character */
288
separator?: string;
289
/** Text prepended to result */
290
prefix?: string;
291
/** Text appended to result */
292
suffix?: string;
293
/** Animation duration in seconds */
294
duration?: number;
295
/** Whether to use easing animation */
296
useEasing?: boolean;
297
/** Whether to use thousands separator grouping */
298
useGrouping?: boolean;
299
/** Whether to use Indian number separators */
300
useIndianSeparators?: boolean;
301
/** Custom easing function */
302
easingFn?: (t: number, b: number, c: number, d: number) => number;
303
/** Custom formatting function */
304
formattingFn?: (value: number) => string;
305
/** Custom numerals array */
306
numerals?: string[];
307
/** Whether to enable scroll spy functionality */
308
enableScrollSpy?: boolean;
309
/** Scroll spy delay in milliseconds */
310
scrollSpyDelay?: number;
311
/** Whether scroll spy should trigger only once */
312
scrollSpyOnce?: boolean;
313
/** CountUp.js plugin */
314
plugin?: any;
315
}
316
317
/** CountUp.js instance returned by getCountUp method */
318
interface CountUpInstance {
319
/** Start the animation */
320
start(callback?: () => void): void;
321
/** Pause or resume the animation */
322
pauseResume(): void;
323
/** Reset to start value */
324
reset(): void;
325
/** Update to new end value */
326
update(newEnd: number | string): void;
327
/** Get formatted value at current state */
328
formattingFn(value: number): string;
329
}
330
```
331
332
## Default Values
333
334
The useCountUp hook provides sensible defaults for all configuration options:
335
336
```typescript
337
const DEFAULTS = {
338
decimal: '.',
339
separator: ',',
340
delay: null,
341
prefix: '',
342
suffix: '',
343
duration: 2,
344
start: 0,
345
decimals: 0,
346
startOnMount: true,
347
enableReinitialize: true,
348
useEasing: true,
349
useGrouping: true,
350
useIndianSeparators: false,
351
};
352
```
353
354
## Advanced Usage Patterns
355
356
### Conditional Animations
357
358
```typescript
359
import React, { useState } from "react";
360
import CountUp from "react-countup";
361
362
function ConditionalCounter() {
363
const [shouldAnimate, setShouldAnimate] = useState(false);
364
365
return (
366
<div>
367
{shouldAnimate && (
368
<CountUp
369
end={100}
370
duration={2}
371
onEnd={() => setShouldAnimate(false)}
372
/>
373
)}
374
<button onClick={() => setShouldAnimate(true)}>
375
Start Animation
376
</button>
377
</div>
378
);
379
}
380
```
381
382
### Multiple Counters with Synchronization
383
384
```typescript
385
import React, { useRef } from "react";
386
import { useCountUp } from "react-countup";
387
388
function SynchronizedCounters() {
389
const ref1 = useRef<HTMLSpanElement>(null);
390
const ref2 = useRef<HTMLSpanElement>(null);
391
392
const counter1 = useCountUp({
393
ref: ref1,
394
end: 100,
395
duration: 2,
396
startOnMount: false,
397
});
398
399
const counter2 = useCountUp({
400
ref: ref2,
401
end: 200,
402
duration: 2,
403
startOnMount: false,
404
});
405
406
const startBoth = () => {
407
counter1.start();
408
counter2.start();
409
};
410
411
return (
412
<div>
413
<span ref={ref1} /> | <span ref={ref2} />
414
<button onClick={startBoth}>Start Both</button>
415
</div>
416
);
417
}
418
```
419
420
### Custom Formatting with Callbacks
421
422
```typescript
423
import CountUp from "react-countup";
424
425
function CustomFormattedCounter() {
426
return (
427
<CountUp
428
end={1234567.89}
429
decimals={2}
430
duration={3}
431
formattingFn={(value) => {
432
// Custom currency formatting
433
return new Intl.NumberFormat('en-US', {
434
style: 'currency',
435
currency: 'USD'
436
}).format(value);
437
}}
438
/>
439
);
440
}
441
```
442
443
## Error Handling
444
445
The library handles common error scenarios:
446
447
- **Missing DOM element**: When using render props, the library logs a warning if `countUpRef` is not attached to a DOM element
448
- **Invalid values**: Non-numeric end values are handled gracefully by CountUp.js
449
- **SSR compatibility**: Uses `useIsomorphicLayoutEffect` to prevent hydration mismatches
450
451
## TypeScript Support
452
453
React CountUp provides complete TypeScript definitions with:
454
455
- Full type safety for all props and callback parameters
456
- Generic type preservation where applicable
457
- Comprehensive interface definitions for all API surfaces
458
- Integration with React's built-in types (CSSProperties, RefObject, etc.)
459
460
## Dependencies
461
462
- **Runtime**: countup.js ^2.8.0
463
- **Peer Dependencies**: react >= 16.3.0
464
- **No additional runtime dependencies**